Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create react component dynamically

Trying to render different components depending on arguments passed with data. If I use regular or React.createElement(Item) - it works fine, but all other options fail.

http://jsfiddle.net/zeen/fmhhtk5o/1/

var React = window.React;  var data = {items: [ { itemClass: 'Item', id: 1, contentsHTML: '', text: 'Item 1'}, { itemClass: 'Item', id: 2, contentsHTML: '', text: 'Item 2'}, { itemClass: 'Item', id: 3, contentsHTML: '', text: 'Item 3'}, { itemClass: 'Item', id: 4, contentsHTML: '', text: 'Item 4'}, { itemClass: 'Item', id: 5, contentsHTML: '', text: 'Item 5'} ]};  var MyCatalog = React.createClass({   getInitialState: function() {     return { data: { items: [] } };   },   componentDidMount: function () {     this.setState({ data: this.props.data });   },    render: function () {     return (       <div className="catalog">         HELLO!!! I AM A CATALOG!!!          <ItemList data={this.state.data}/>       </div>     );   } });  var ItemList = React.createClass({   render: function () {     console.log(this.props);      var items = this.props.data["items"].map(function (itemData) {      var klass = itemData['itemClass'] || 'Item';     var ItemFactory = React.createFactory(klass);      //return <ItemFactory key={itemData['id']} data={itemData}/> // no     //return <klass key={itemData['id']} data={itemData}/> // no     //return React.createElement(klass, { key: itemData['id'], data: itemData }); // no     //return <Item data={itemData}/> // ok     //return React.createElement(Item, { data: itemData }); // ok     //return React.createElement('Item', { key: itemData['id'], data: itemData }); // no     //return React.createElement(React.createFactory('Item'), { data: itemData }); // no, error     var component = Components['itemClass'];     return <component data={itemData} key={itemData['id']}/>       });    console.log(items);   return (     React.createElement('div', { className: 'list' },       React.createElement('div', null, 'And I am an ItemList :'),         React.createElement('div', null, items)       )        /*<div className="list">       <div>And I am an ItemList :</div>       <div>         {items}       </div>       </div>*/     );   } });  var Item = window.Item = React.createClass({   render: function () {     return (       <div className="item">         <div>           Regular item. Nothing special.         </div>           {this.props.children}         </div>       );     }   });    var Components = { 'Item': Item };    React.render(      <MyCatalog data={data}/>,      document.getElementById('app')    ); 

How can I manage this case for different types of components?

like image 842
Dmytro Avatar asked Jul 05 '15 20:07

Dmytro


People also ask

Is it possible to dynamically create components in react native?

Yes it is possible to dynamically create components in React Native based on data you retrieve from the server.

How do you render a component dynamically based on a JSON?

To render the components based on the component key in the JSON config, we first need to create an object that maps the components with the component key. As you can see, I have mapped the component key with the corresponding Reactstrap component. At the top, we will import all the required components.


2 Answers

This should work:

var component = Components[itemData['itemClass']]); return React.createElement(component, {     data: itemData,     key: itemData['id'] }); 

You can't use JSX syntax like this <component .../> because when it gets transpiled component won't refer to anything.

UPDATE: Here is the updated ItemList component in full:

var ItemList = React.createClass({     render: function() {         console.log(this.props);          var items = this.props.data["items"].map(function(itemData) {             var component = Components[itemData['itemClass']];             return React.createElement(component, {                 data: itemData,                 key: itemData['id']             });         });         console.log(items);         return (             <div className="list">                 <div>And I am an ItemList</div>                 <div>{items}</div>             </div>         );     } }); 

You can see it working in this fiddle: http://jsfiddle.net/fmhhtk5o/3/

like image 61
rojoca Avatar answered Oct 02 '22 22:10

rojoca


The accepted answer is not entirely accurate and it is overly complex.

You can't use JSX syntax like this <component .../> because when it gets transpiled component won't refer to anything.

Just capitalize the variable name to avoid this, ie.

const component = ({ChildClass}) => {     return <ChildClass /> } 
like image 20
wilco Avatar answered Oct 02 '22 20:10

wilco