1

I'm trying to render dynamically named React components. I understand the JSX requires the variable name to be capitalized. However, when I map over my state and try to populate components, I get the following error:

Warning: <TextBlock /> is using uppercase HTML. Always use lowercase HTML tags in React.

I understand this, and capitalization seems to work in the child TextBlock if I don't use a map and type out directly in the render of the main class.

Main class:

import React from 'react';
import TextBlock from './Components/TextBlock';

class RenderView extends React.Component {
  constructor() {
    super();

    this.state = {
      blurbs: [
        {
          value: "Text value",
          tag: "h2",
          component: 'TextBlock'
        },
        {
          value: "lorem stuff adnfsaldkfn asdfl lkjasdflkj asdlfk  alskdjflaksdjf ",
          tag: "p",
          component: 'TextBlock'
        }
      ]
    }
  }

  render() {

    const componentArray = this.state.blurbs.map((blurb, index) => {
      const Tag = blurb.component;
      return <Tag obj={blurb} key={index} />;
    })

    return componentArray;
  }
}

Child component TextBlock:

import React from 'react';

export default function TextBox(props) {

  const Tag = props.obj.tag;

  const Output = <Tag>{props.obj.value}</Tag>

  return Output;
}

Checking the react chrome tools, it appears to be rendering as an html element. How do I get react to recognize these two blurbs are jsx elements?

Jim
  • 35
  • 6

1 Answers1

1

I'm not sure how dynamic you need it to be (if it has to be a string or it can always be a reference to a react component), but it should work if you use the component reference directly instead of a string:

this.state = {
  blurbs: [
    {
      value: "Text value",
      tag: "h2",
      component: TextBlock
    },

If you really need to do it with strings, then you could add the components to a map and render them that way:

const COMPONENTS = {
  TextBlock,
  // etc..
};

--

const Tag = COMPONENTS[blurb.component];
Austin Greco
  • 32,997
  • 6
  • 55
  • 59
  • It looks like referencing directly works fine. I think the map solution will work best here, thanks! Do you know why it wouldn't take the above code? – Jim Nov 25 '17 at 13:34
  • Since i just a string, react has no way of knowing what component 'TextBlock' would be. There is no way to register a component, so you need to tell it exactly what you mean via a reference. – Austin Greco Nov 26 '17 at 03:28