在 React JSX 中循环

IT技术 javascript reactjs jsx
2021-02-02 03:11:45

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

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

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

6个回答

把它想象成你只是在调用 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 are adding 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 的工作原理。

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

如果这是您的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>
如果迭代对象是数组,则 Map 更有意义;如果是数字,则 for 循环是合适的。
2021-03-11 03:11:45
<tbody>{objects.map((o, i) => <ObjectRow obj={o} key={i}/>}</tbody> 使用 Reactify 的 ES6 支持或 Babel。
2021-04-08 03:11:45

如果您还没有一个map()喜欢@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.8.23) 在传播实际的Array. 我有一个文档问题可以澄清这一点。但使用风险自负或使用 polyfill。

香草 ES5

Array.apply

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

有了Array.prototype.fill你能做到这一点,以替代使用作为传播上面所示:

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

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

key

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

请不要仅仅为了从 0..N 迭代而创建一个数组。这是 Javascript 的峰值。
2021-03-11 03:11:45

简单地使用带有 ES6 语法的map Array方法:

<tbody>
  {items.map(item => <ObjectRow key={item.id} name={item.name} />)} 
</tbody>

不要忘记key财产。

我添加了一个随机的 'Math.random()' 键而不是 id 当 setState 在孩子内部时它不能正常工作,知道为什么吗?
2021-03-23 03:11:45

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

另外,不要忘记根据需要为每次迭代设置一个唯一的 Key地图功能创建一个从0唯一索引,但它不使用产生的索引建议,但如果你的值是唯一的,或者如果有一个独特的键,你可以使用它们:

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

另外,如果您不熟悉 Array 上的 map 函数,请MDN 中获取几行

map 为数组中的每个元素依次调用一次提供的回调函数,并根据结果构造一个新数组。仅对已分配值(包括未定义)的数组索引调用回调。对于数组中缺失的元素(即从未设置、已删除或从未赋值的索引),不会调用它。

callback 使用三个参数调用:元素的值、元素的索引和被遍历的 Array 对象。

如果向地图提供了 thisArg 参数,它将用作回调的 this 值。否则,值 undefined 将用作它的 this 值。回调最终可观察到的这个值是根据确定函数看到的 this 的通常规则确定的。

map 不会改变它被调用的数组(尽管回调,如果被调用,可能会这样做)。

Array#map 不是异步的!
2021-03-18 03:11:45