最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Create react component dynamically - Stack Overflow

programmeradmin1浏览0评论

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?

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?

Share Improve this question edited Jul 7, 2018 at 15:33 ThomasThiebaud 12k6 gold badges56 silver badges78 bronze badges asked Jul 5, 2015 at 20:08 DmytroDmytro 2,2273 gold badges21 silver badges32 bronze badges 3
  • What is preventing you from using JSX notation in your ItemList? – E_net4 Commented Jul 5, 2015 at 20:23
  • When you say "passed as data" do you means as this.props.{propertyName] value? Why not just stick with using this.props.children and pass them in as child nodes - Which is after all a property. Or define a number of possible component type and then return a variable that isa component inside a swicth – Code Uniquely Commented Jul 5, 2015 at 21:17
  • @E_net4 as you can see I used JSX also, but it doesn't work – Dmytro Commented Jul 6, 2015 at 20:26
Add a comment  | 

2 Answers 2

Reset to default 55

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/

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 />
}
发布评论

评论列表(0)

  1. 暂无评论