我试图在React JSX(其中ObjectRow是一个单独的组件)中执行以下操作:
<tbody>
for (var i=0; i < numrows; i++) {
<ObjectRow/>
}
</tbody>
我意识到并理解为什么这不是有效的JSX,因为JSX映射到函数调用。然而,由于来自模板领域,而且是JSX的新手,我不确定如何实现上述目标(多次添加组件)。
我试图在React JSX(其中ObjectRow是一个单独的组件)中执行以下操作:
<tbody>
for (var i=0; i < numrows; i++) {
<ObjectRow/>
}
</tbody>
我意识到并理解为什么这不是有效的JSX,因为JSX映射到函数调用。然而,由于来自模板领域,而且是JSX的新手,我不确定如何实现上述目标(多次添加组件)。
当前回答
您只能在JSX元素中编写JavaScript表达式,因此for循环无法工作。您可以先将元素转换为数组,然后使用map函数渲染它:
<tbody>
{[...new Array(numrows)].map((e) => (
<ObjectRow/>
))}
</tbody>
其他回答
假设您所在的州有一系列项目:
[{name: "item1", id: 1}, {name: "item2", id: 2}, {name: "item3", id: 3}]
<tbody>
{this.state.items.map((item) => {
<ObjectRow key={item.id} name={item.name} />
})}
</tbody>
如果您已经在使用lodash,_.times函数很方便。
import React, { Component } from "react";
import Select from "./Select";
import _ from "lodash";
export default class App extends Component {
render() {
return (
<div className="container">
<ol>
{_.times(3, (i) => (
<li key={i}>repeated 3 times</li>
))}
</ol>
</div>
);
}
}
以下是React文档中的一个示例,JavaScript表达式作为子项:
function Item(props) {
return <li>{props.message}</li>;
}
function TodoList() {
const todos = ['finish doc', 'submit pr', 'nag dan to review'];
return (
<ul>
{todos.map((message) => <Item key={message} message={message} />)}
</ul>
);
}
至于你的情况,我建议你这样写:
function render() {
return (
<tbody>
{numrows.map((roe, index) => <ObjectRow key={index} />)}
</tbody>
);
}
请注意,键非常重要,因为React使用键来区分数组中的数据。
React元素是简单的JavaScript,因此您可以遵循JavaScript的规则。您可以在JavaScript中使用for循环,如下所示:-
<tbody>
for (var i=0; i < numrows; i++) {
<ObjectRow/>
}
</tbody>
但有效且最好的方法是使用.map函数。如下所示:-
<tbody>
{listObject.map(function(listObject, i){
return <ObjectRow key={i} />;
})}
</tbody>
在这里,有一件事是必要的:定义密钥。否则,它将发出如下警告:-
Warning.js:36警告:数组或迭代器中的每个子级都应该具有独特的“钥匙”道具。检查ComponentName的渲染方法。看见“链接”了解更多信息。
如果您还没有像@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
在所有情况下,关键属性都会减轻开发构建的警告,但在孩子中无法访问。如果希望子级中的索引可用,可以传递额外的属性。有关讨论,请参见列表和键。