如何使用 map 和 join 来渲染 react 组件?

IT技术 reactjs
2021-03-31 11:20:39

我有一个组件将显示字符串数组。代码如下所示:

React.createClass({
  render() {
     <div>
        this.props.data.map(t => <span>t</span>)
     </div>
  }
})

它工作得很好。即如果props.data = ['tom', 'jason', 'chris'],页面中呈现的结果将是tomjasonchris

然后,我想使用逗号连接所有名称,因此我将代码更改为:

this.props.data.map(t => <span>t</span>).join(', ')

但是,呈现的结果是[Object], [Object], [Object]

我不知道如何解释对象成为要渲染的react组件。有什么建议吗?

6个回答

一个简单的解决方案是不使用reduce()第二个参数并且不传播先前的结果:

class List extends React.Component {
  render() {
     <div>
        {this.props.data
          .map(t => <span>{t}</span>)
          .reduce((prev, curr) => [prev, ', ', curr])}
     </div>
  }
}

如果没有第二个参数,reduce()将从索引 1而不是 0 开始,并且 React 对嵌套数组非常满意。

正如评论中所说,您只想将它​​用于至少有一项的数组,因为reduce()没有第二个参数将抛出一个空数组。通常,这应该不是问题,因为无论如何您都想显示一条自定义消息,说“这是空的”之类的空数组。

更新typescript

您可以在 Typescript 中使用它(没有 type-unsafe any),React.ReactNode类型参数为.map()

class List extends React.Component {
  render() {
     <div>
        {this.props.data
          .map<React.ReactNode>(t => <span>{t}</span>)
          .reduce((prev, curr) => [prev, ', ', curr])}
     </div>
  }
}
If the array is empty and no initialValue was provided, TypeError would be thrown.. 所以它不适用于空数组。
2021-05-30 11:20:39
有人让这个解决方案与 React + TypeScript 一起工作吗?
2021-06-03 11:20:39
@Jstuff 我不得不使用任何一个。 .reduce((prev: JSX.Element, current: JSX.Element): any => [prev, (<span>&nbsp;</span>), current])
2021-06-14 11:20:39
另请注意,这会递归嵌套prev数组。例如[1, 2, 3, 4]变成[[[1,",",2],",",3],",",4]
2021-06-16 11:20:39
@Tamlyn:你认为我最初在答案中提到你的观点(“React 对嵌套数组非常满意”)足够清楚还是我应该详细说明一下?
2021-06-18 11:20:39

您可以使用reduce组合数组的多个元素:

React.createClass({
  render() {
     <div>
        this.props.data
        .map(t => <span>t</span>)
        .reduce((accu, elem) => {
            return accu === null ? [elem] : [...accu, ',', elem]
        }, null)
     </div>
  }
})

这将用 null 初始化累加器,因此我们可以将第一项包装在一个数组中。对于数组中的每个后续元素,我们使用 构造一个包含所有先前元素的新数组...-operator,添加分隔符,然后添加下一个元素。

Array.prototype.reduce()

@Guy 你绝对正确 - 我的错误是我用空格连接值,并且在渲染输出中缺少空跨度
2021-05-27 11:20:39
谢谢,正是我需要的。您可以通过将累加器初始化为空数组来删除空检查和三元
2021-06-14 11:20:39
@Larry 如果您删除空检查和三元,并通过 [] 作为初始值设定项,您如何避免前导逗号?['a'].reduce((a, e) => [...a, ',', e],[])产量[",", "a"]除非数组为空,否则不传递初始值设定项是有效的,在这种情况下它返回一个 TypeError。
2021-06-14 11:20:39

React 16 更新:现在可以直接渲染字符串,因此您可以通过删除所有无用<span>标签来简化代码。

const list = ({ data }) => data.reduce((prev, curr) => [ prev, ', ', curr ]);

如果我只想渲染一个逗号分隔的组件数组,我通常会觉得reduce太冗长了。在这种情况下更短的解决方案是

{arr.map((item, index) => (
  <Fragment key={item.id}>
    {index > 0 && ', '}
    <Item {...item} />
  </Fragment>
))}

{index > 0 && ', '} 将在除第一个之外的所有数组项前面呈现一个逗号,后跟一个空格。

如果你想用别的东西把倒数第二个和最后一个分开,比如 string ' and ',你可以{index > 0 && ', '}

{index > 0 && index !== arr.length - 1 && ', '}
{index === arr.length - 1 && ' and '}
我喜欢这个,对于像我这样的 React 新手来说,这个解决方案最容易理解:)
2021-05-23 11:20:39
您可能更常见地将其<Fragment></Fragment>视为简写<></>但是在这种情况下,必须使用更长的版本,因为列表中的每个项目都需要一个唯一的key,并且您不能添加key<></>但是,您可能不需要<Item>, ifitem已经是一个组件。
2021-05-25 11:20:39

接受的答案实际上返回一个数组数组,因为prev每次都是一个数组。React 足够聪明来完成这项工作,但是它是否容易在将来导致问题,例如在为 map 的每个结果提供键时破坏 Reacts diffing 算法。

React.Fragment功能让我们以一种易于理解的方式做到这一点,而没有潜在的问题。

class List extends React.Component {
  render() {
     <div>
        {this.props.data
          .map((t, index) => 
            <React.Fragment key={index}>
              <span> {t}</span> ,
            </React.Fragment>
          )
      </div>
  }
}

随着React.Fragment我们可以简单地将分离器,的返回的HTML之外并做出react不会抱怨。

很棒的解决方案,但您需要删除数组最后一个元素的逗号
2021-05-29 11:20:39
@JohnP 在前面添加更容易:<React.Fragment key={index}>{index ? ',' : ''}<span>{t}</span></React.Fragment>
2021-06-02 11:20:39
您可以通过此修改删除最后一个逗号: <React.Fragment key={index}> <span> {t}</span> {index === this.props.data.length - 1 ? '' : ','} </React.Fragment>
2021-06-05 11:20:39
你总是可以使用车削和索引来解决这个问题。
2021-06-10 11:20:39