5

I want to dynamically render a react component from its string-name. Here is what I have done, but it does not work. Can this be done ? An example would really help.

string_name is the name of the component.

var MyComponent = React.createElement(window[string_name], {});
return (
      <div className="wrapper">
          <div>Hello World</div>
          <MyComponent/>
      </div>
    )

2 Answers 2

8

The key bit missing, and I don't know if it's documented anywhere, but you need to use a capital letter for the JSX compiler (?) to recoginise it as a type.

import AllComponents from 'Components';

const FooType = 'Foo';

return (
    <div className="wrapper">
        <div>Hello World</div>
        <AllComponents[FooType] />
    </div>
);

Edit - As per the comments

class Foo extends React.Component {
    render() { 
        return <div>Foo 123</div>; 
    }
};

class Bar extends React.Component {
    render() { 
        return <div>Bar 123</div>; 
    }
};


class App extends React.Component {


  render() {
    const all = {
        'Foo': Foo,
        'Bar': Bar,    
    };

    // For the sake of the demo, just randomly pick one of the two
    // usually this would come from an import, or something similar
    const randomKey = ['Foo', 'Bar'][Math.floor(Math.random() * 2)];

    // The resolved component must begin with a capital letter
    const Type = all[randomKey];


    return (
        <div>
            <Type />
        </div>    
    );
  }

};


ReactDOM.render(<App />, document.getElementById('root')); 

JSBin: http://jsbin.com/noluyu/5/edit?js,output

Edit 2

Our typical apps that render components dynamically, usually have an index.js file at the root of all the components directory, that simple list all possible components:

// index.js
export Breadcrumb                from './breadcrumb/Breadcrumb';
export Checkbox                  from './checkbox/Checkbox';
export Comment                   from './comment/Comment';

Then all you have to do is something like:

import AllComponents from './index.js';

const myType = 'Checkbox';
const Type = AllComponents[myType];

.. later ..
return <div><Type /></div>;
Sign up to request clarification or add additional context in comments.

5 Comments

Obviously you need a have a list of available components. I will edit, to show an inline example...
But I cannot manually list all components. Is there any other way to do this dynamically.
No, as they need to be imported in some fashion, otherwise your module loader (be in native, or browseify , or whatever) will never know to pull those modules in. I have updated the answer again, to show a stream lined version of this
Here is a working fiddle which dynamically picks the component name. If I write some other html tags before <Component/ > tag it does not work. jsfiddle.net/geetamamuni/q3zwtosw/19
Ok got it, it works now. I am accepting your answer as it is also an alternative approach. Thanks.
0

One thing you can do is require a child component within MyComponent and render it in your return. Write your custom function to render the component dynamically in the Child, then require it in MyComponent.

var React = require('react');

var Names = React.createClass({
  render: function(){

    // Map the names and loop through
    var names = this.props.names.map(function(name, index){

        return(
            <div> 
                <li className="list-group-item" key={index}>
                  {<h4>{name[index]}</h4>}

                </li>
            </div>
        )
    });
  }
});

/*We then export the Names component*/
module.exports = Names;

Below is the Parent component.

var React = require('react');
var Names = require('./Names');

var MyComponent = React.createClass({
/*This will set the initial state for any state the component handles. usually empty data*/
 getInitialState: function(){
    return {

       names: ["My Component", "Your Component"]

    }
 },


 render: function(){

    return(

        <div className="row">

            <div className="col-md-4">

                <Names names={this.state.names} />

            </div>

        </div>
    );
 }
});

3 Comments

Wouldn't name.name in the h4 be undefined as you are mapping the flat array of strings?
Here is a working fiddle which dynamically picks the component name. If I write some other html tags before <Component/ > tag it does not work. jsfiddle.net/geetamamuni/q3zwtosw/19
@GeetanjaliPanda Honestly, there are more practical ways to solve the problem. In your fiddle, you are ultimately rendering a component to the window. You should be passing data as props from the Parent to the Child, or Owner to the Owned, this is the React way. Then, you can write any custom function you want to make the data display dynamically.

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.