10

I was trying to call a component dynamically like this

var Tagname = 'Species';
options.push(<Tagname {...attrs}/>);

And im getting a warning in the console as

Warning: <Species /> is using uppercase HTML. Always use lowercase HTML tags in React.
Warning: The tag <Species> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.

All other codes are working fine. But this component does not working. How can i fix this?

3
  • 1
    React.createElement(Tagname, attrs) Commented Feb 19, 2018 at 10:12
  • @TryingToImprove I also tried with this and same console warning arrives Commented Feb 19, 2018 at 10:40
  • See the warning. The first one says that you are using uppercased HTML inside your render. Do you do <DIV.... for instance? Commented Feb 19, 2018 at 11:12

2 Answers 2

26

Yes you can call the component dynamically, but it should be the component itself not the string.

Like this:

var Tagname = Species;    //component itself, not string
<Tagname {...attrs}/>;

Because JSX will get compiles into React.createElement(Component, props, ...children) and Component will be a string if it a html tag, otherwise a react component.

So if you pass React.createElement("Species", props, ...children), react will treat it as a html tag not a react component.

Update:

You can do one thing, create a map for each component, Like this:

const Map = {
  "componenet1": Component1,
  "componenet2": Component2
}

Now you can access the component using the string key, like this:

let name = "componenet1";
let Tagname = Map[name];
<Tagname {...attrs}/>;
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Mayank. This works. But i have the value Species in a variable and when i tried to assign the variable it takes only as string. Eg: var Tagname=this.state.value; How to fix this?
@HareeshSNair, you can do one thing, create a map of string and component name, and use that map to get the component from string, check the Update section of the answer :)
Would it be correct to render anything from my app? let's say I do import * as MyComponents from 'components', where I get all of them and then I can choose from there using my string as an index.
@rmartrenado yes that will also be a good option, save the mapping in a different file then render them using some string.
-1

The following works for me...Just pass as full component tags from parent component and render in child component's jsx as normal variable.

Parent component:

export const ParentComponent = () => {
    const rows = [
      {component: <Comp1 />},
      {component: <Comp2 />},
    ]
    return ( <ChildComponent rows={rows} /> );
   }

Child component:

export const ChildComponent = ({rows}) => {
     return(
      <div>
          {rows.map((r)=>{
            return(
              r.component
            )
          })}
      </div>
     )
   }

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.