我试图在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元素方面有很多解决方案。所有这些都很好,但都直接在循环中使用了索引。我们建议使用数据中的唯一id作为键,但如果数组中的每个对象没有唯一id,我们将使用索引作为键,但是不建议直接使用索引作为密钥。
还有一件事,为什么我们选择.map,但为什么不选择foEach,因为.map返回一个新数组。现在有很多不同的方法。
下面使用.map的不同版本详细说明了如何使用唯一键以及如何使用.map循环JSX元素。
当从数据中返回单个JSX元素和唯一id作为密钥版本时,.map不返回:
const {objects} = this.state;
<tbody>
{objects.map(object => <ObjectRow obj={object} key={object.id} />)}
</tbody>
将数据中的多个JSX元素和唯一id作为密钥版本返回时,不返回.map
const {objects} = this.state;
<tbody>
{objects.map(object => (
<div key={object.id}>
<ObjectRow obj={object} />
</div>
))}
</tbody>
当将单个JSX元素和索引作为键版本返回时,.map没有返回:
const {objects} = this.state;
<tbody>
{objects.map((object, index) => <ObjectRow obj={object} key={`Key${index}`} />)}
</tbody>
当返回多个JSX元素和索引作为密钥版本时,.map没有返回:
const {objects} = this.state;
<tbody>
{objects.map((object, index) => (
<div key={`Key${index}`}>
<ObjectRow obj={object} />
</div>
))}
</tbody>
.map,当返回多个JSX元素和索引作为键版本时返回:
const {objects} = this.state;
<tbody>
{objects.map((object, index) => {
return (
<div key={`Key${index}`}>
<ObjectRow obj={object} />
</div>
)
})}
</tbody>
将数据中的多个JSX元素和唯一id作为密钥版本返回时,使用return的.map:
const {objects} = this.state;
<tbody>
{objects.map(object => {
return (
<div key={object.id}>
<ObjectRow obj={object} />
</div>
)
})}
</tbody>
另一种方式是
render() {
const {objects} = this.state;
const objectItems = objects.map(object => {
return (
<div key={object.id}>
<ObjectRow obj={object} />
</div>
)
})
return(
<div>
<tbody>
{objectItems}
</tbody>
</div>
)
}
其他回答
您可以从numRows创建数组并映射它
像这样的东西:
<tbody>
{Array.from({ length: numrows }).map((_,i)=><ObjectRow key={i}/>)
</tbody>
有几个答案指向使用map语句。下面是一个完整的示例,它使用FeatureList组件中的迭代器基于一个称为features的JSON数据结构列出Feature组件。
const FeatureList = ({ features, onClickFeature, onClickLikes }) => (
<div className="feature-list">
{features.map(feature =>
<Feature
key={feature.id}
{...feature}
onClickFeature={() => onClickFeature(feature.id)}
onClickLikes={() => onClickLikes(feature.id)}
/>
)}
</div>
);
您可以在GitHub上查看完整的FeatureList代码。此处列出了特征夹具。
如果您还没有像@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
在所有情况下,关键属性都会减轻开发构建的警告,但在孩子中无法访问。如果希望子级中的索引可用,可以传递额外的属性。有关讨论,请参见列表和键。
我用它就像
<tbody>
{ numrows ? (
numrows.map(obj => { return <ObjectRow /> })
) : null
}
</tbody>
你必须用JSX写:
<tbody>
{
objects.map((object, i) => (
<ObjectRow obj={object} key={i} />
));
}
</tbody>