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.

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?

3

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:

3

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 /> } 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like