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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.