How to render an array of JSX elements (React comp

2019-07-25 07:37发布

问题:

I'm trying to render an array of named react components, say <Foo />, <Bar />, and <Baz />,for example.

const rendered = [];
const getItems = this.props.itemslist.map((item, key) => {
const TYPE = item.type;
rendered.push(<TYPE data-attributes={attributes} key={key} />);
});
return (
  <Grid>
    <Row>
    {rendered}
    </Row>
  </Grid>
);

I can iterate over my array and see in the console the array of elements, but they are rendered as empty html elements "<foo></foo><bar></bar><baz></baz>", and not the actual components. Why is this happening and, more importantly, how can I get the COMPONENTS to render?

回答1:

You should use component instead of string in item.type like this

import Foo from './Foo';
import Bar from './Bar';

[ { type: Foo, }, { type: Bar, }, { type: Baz}]

UPDATE:

If you do not have component reference in advance then use a mapping object which convert your string to component reference like this

import Foo from './Foo';
import Bar from './Bar';

const mapper = {
  Foo: Foo,
  Bar: Bar,
}

// Then use it like this

const getItems = this.props.itemslist.map((item, key) => {
    const Type = mapper[item.type];
    rendered.push(<Type data-attributes={attributes} key={key} />);
});


回答2:

The first mistake is see if an incorrect use of .map. Remember that .map traverses each array element and changes them. Right now, you are using it as if it were .forEach.

Your code should look more like this:

const getItems = this.props.itemslist.map((item, key) => {
  const TYPE = item.type;
  return <TYPE data-attributes={attributes} key={key} />
});


回答3:

You can use React.createElement for creating the React element with a dynamic name. Also make sure to import those components.

const rendered = [];
const getItems = this.props.itemslist.map((item, key) => {
    const component = React.createElement(item.type, {data-attributes: attributes, key: key}, null);
    rendered.push(component);
});
return (
  <Grid>
    <Row>
    {rendered}
    </Row>
  </Grid>
);