我试图在React JSX(其中ObjectRow是一个单独的组件)中执行以下操作:

<tbody>
    for (var i=0; i < numrows; i++) {
        <ObjectRow/>
    } 
</tbody>

我意识到并理解为什么这不是有效的JSX,因为JSX映射到函数调用。然而,由于来自模板领域,而且是JSX的新手,我不确定如何实现上述目标(多次添加组件)。


当前回答

在渲染或任何函数中,在返回之前,可以使用变量来存储JSX元素。就像这样-

const tbodyContent = [];
for (let i=0; i < numrows; i++) {
    tbodyContent.push(<ObjectRow/>);
}

在身体内部使用它,如下所示:

<tbody>
    {
        tbodyContent
    }
</tbody>

但我更喜欢map()而不是这个。

其他回答

好了,给你。

{
    [1, 2, 3, 4, 5, 6].map((value, index) => {
        return <div key={index}>{value}</div>
    })
}

您所要做的只是映射数组并返回任何要渲染的内容。请不要忘记在返回的元素中使用key。

使用Array映射函数是一种非常常见的循环遍历元素数组并在React中根据元素创建组件的方法。这是一种很好的循环方式,非常有效,也是在JSX中进行循环的一种整洁的方式。这不是唯一的方法,而是首选的方法。

此外,不要忘记根据需要为每个迭代提供唯一的Key。map函数从0创建一个唯一索引,但不建议使用生成的索引,但如果您的值是唯一的或存在唯一的键,则可以使用它们:

<tbody>
  {numrows.map(x=> <ObjectRow key={x.id} />)}
</tbody>

此外,如果您不熟悉Array上的map函数,MDN中的几行代码:

map为数组,并根据结果构造一个新数组。回调仅对具有赋值的数组的索引调用,包括未定义的。对于缺少数组(即从未设置过的索引删除或从未被赋值)。回调是用三个参数调用的:元素的值,元素的索引和正在遍历的Array对象。如果向映射提供了thisArg参数,它将用作callback就是这个值。否则,未定义的值将用作这就是它的价值。回调最终可观察到的值为根据通常的规则确定通过函数。map不会改变调用它的数组(尽管回调(如果调用)可能会这样做)。

问题是您没有返回任何JSX元素。对于这种情况还有另一种解决方案,但我将提供最简单的解决方案:“使用map函数”!

<tbody>
  { numrows.map(item => <ObjectRow key={item.uniqueField} />) }
</tbody>

它是如此简单和美丽,不是吗?

如果您还没有像@FakeRainBrigand的答案那样的要映射()的数组,并且希望内联该数组,以使源布局与比@SophieAlpert的答案更接近的输出相对应:

使用ES2015(ES6)语法(扩展和箭头函数)

http://plnkr.co/edit/mfqFWODVy8dKQQOkIEGV?p=preview

<tbody>
  {[...Array(10)].map((x, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

回复:使用Babel进行传输时,其警告页面显示Array.from是传播所必需的,但目前(v5.2.23)在传播实际的Array时似乎并非如此。我有一个文件问题需要澄清。但请自行承担风险或使用polyfill。

香草ES5

阵列应用

<tbody>
  {Array.apply(0, Array(10)).map(function (x, i) {
    return <ObjectRow key={i} />;
  })}
</tbody>

内联IIFE

http://plnkr.co/edit/4kQjdTzd4w69g8Suu2hT?p=preview

<tbody>
  {(function (rows, i, len) {
    while (++i <= len) {
      rows.push(<ObjectRow key={i} />)
    }
    return rows;
  })([], 0, 10)}
</tbody>

其他答案的技术组合

保持与输出相对应的源布局,但使内联部分更紧凑:

render: function () {
  var rows = [], i = 0, len = 10;
  while (++i <= len) rows.push(i);

  return (
    <tbody>
      {rows.map(function (i) {
        return <ObjectRow key={i} index={i} />;
      })}
    </tbody>
  );
}

使用ES2015语法和数组方法

对于Array.prototype.fill,您可以这样做,作为使用如上所示的排列的替代方法:

<tbody>
  {Array(10).fill(1).map((el, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

(我认为你实际上可以省略fill()的任何参数,但我不是100%。)感谢@FakeRainBrigand在fill()解决方案的早期版本中纠正了我的错误(请参阅修订版)。

key

在所有情况下,关键属性都会减轻开发构建的警告,但在孩子中无法访问。如果希望子级中的索引可用,可以传递额外的属性。有关讨论,请参见列表和键。

我不确定这是否适用于您的情况,但通常地图是一个很好的答案。

如果这是使用for循环的代码:

<tbody>
    for (var i=0; i < objects.length; i++) {
        <ObjectRow obj={objects[i]} key={i}>
    }
</tbody>

你可以用地图这样写:

<tbody>
    {objects.map(function(object, i){
        return <ObjectRow obj={object} key={i} />;
    })}
</tbody>

ES6语法:

<tbody>
    {objects.map((object, i) => <ObjectRow obj={object} key={i} />)}
</tbody>