提问者:小点点

React JSX内部循环


我尝试在ReactJSX(其中ObjectRow是一个单独的组件)中执行如下操作:

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

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


共3个答案

匿名用户

就像调用JavaScript函数一样。不能使用for循环来执行函数调用的参数:

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

查看如何将tbody函数传递给for循环作为参数-导致语法错误。

但您可以创建一个数组,然后将其作为参数传入:

var rows = [];
for (var i = 0; i < numrows; i++) {
    rows.push(ObjectRow());
}
return tbody(rows);

在使用JSX时可以使用基本相同的结构:

var rows = [];
for (var i = 0; i < numrows; i++) {
    // note: we add a key prop here to allow react to uniquely identify each
    // element in this array. see: https://reactjs.org/docs/lists-and-keys.html
    rows.push(<ObjectRow key={i} />);
}
return <tbody>{rows}</tbody>;

顺便提一下,我的JavaScript示例几乎完全是JSX示例的转换结果。使用Babel REPL来了解JSX的工作原理。

匿名用户

不确定这是否适合你的情况,但通常地图是一个很好的答案。

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

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

你可以用map这样写:

<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>

匿名用户

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

http://plnkr.co/edit/mfqfwodvy8dkqqokiegv?p=预览

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

RE:使用Babel进行Transspiling,它的警告页面上说array.from是扩散所必需的,但目前(v5.8.23)在扩散实际的array时似乎不是这样。我有一个文件问题要澄清这一点。但使用风险自负或使用聚氯乙烯。

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

http://plnkr.co/edit/4kqjdtzd4w69g8suu2ht?p=预览

<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>
  );
}

使用array.prototype.fill,可以将此操作作为使用扩展的替代方法,如上所示:

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

(我认为您实际上可以省略fill()的任何参数,但我对此不是百分之百的理解。)感谢@FakeraInbrigand纠正了我在fill()解决方案的早期版本中的错误(请参阅修订)。

在所有情况下,keyattr都可以减轻开发构建中的警告,但在子版本中不可访问。如果希望子级中的索引可用,可以传递额外的attr。有关讨论,请参阅列表和关键字。