在 React JSX 中返回成对的元素

IT技术 javascript reactjs react-jsx
2021-05-03 14:46:54

问题:

在 React 中,你想通过映射一个数组来创建一个 DOM 结构,但是数组中的每一项都应该返回 2 个元素。例如

import React from 'react'
import _ from 'lodash'

let { Component } = React

export default class DataList extends Component {
  render () {
    let array = [
      {def: 'item1', term: 'term1', obj1: 'rand'}, 
      {def: 'item2', term: 'term2'}
    ]
    return (
      <dl>
        {_.map(array, (item) => {
          return (
            <dt>{item.def}</dt>
            <dd>{item.term}</dd>
          )
        })}
      </dl>
    )
  }
}

React 不允许你在不将它们包装在容器元素中的情况下渲染兄弟姐妹,这会破坏 DOM 结构。

3个回答

你可以reduce像这样做一些更简单的事情

import React, { Component } from 'react';

export default class DataList extends Component {
  render () {
    const array = [
      {def: 'item1', term: 'term1', obj1: 'rand'}, 
      {def: 'item2', term: 'term2'}
    ];

    return (
      <dl>
        {array.reduce((acc, item, idx) => {
            return acc.concat([
                <dt key={`def-${idx}`}>{item.def}</dt>,
                <dd key={`term-${idx}`}>{item.term}</dd>
            ]);
        }, [])}
      </dl>
    );
  }
}

演示 :: https://jsfiddle.net/rifat/caray95v/

React 16.2 添加了对 的支持Fragments,你可以像这样使用它:

return (
  <dl>
    {_.map(array, (item) => {
      return (
        <Fragment>
          <dt>{item.def}</dt>
          <dd>{item.term}</dd>
        </Fragment>
      )
    })}
  </dl>
)

您还可以使用带有空标签的 Fragment,如下所示:

return (
  <dl>
    {_.map(array, (item) => {
      return (
        <>
          <dt>{item.def}</dt>
          <dd>{item.term}</dd>
        </>
      )
    })}
  </dl>
)

但请记住,如果您想使用标签key属性,Fragment则必须使用它的完整版本。有关react 博客的更多信息

我发现实现这一点的最简单方法是为数组的每个项目映射对象键(lodash 支持这一点)并有条件地渲染每种类型的元素。

import React from 'react'
import _ from 'lodash'

let { Component } = React

export default class DataList extends Component {
  render () {
    let array = [
      {def: 'item1', term: 'term1', obj1: 'rand'}, 
      {def: 'item2', term: 'term2'}
    ]

    return (
      <dl>
        {_.map(array, (item) => {
          return _.map(item, (elem, key) => {
            if (key === 'def') {
              return <dt>{elem}</dt>
            } else if (key === 'term') {
              return <dd>{elem}</dd>
            }
          })
        })}
      </dl>
    )
  }
}