在这篇文章中,我们将介绍如何在React中用JSX输出一个元素n次。这并不像我们想象的那样直接。

一个例子
这里有一个React中的组件的片段,它需要添加一些由用户指定的动态字段:
const [
inputfieldsToAdd,
setInputfieldsToAdd,
] = React.useState(1);
const [
committedFieldsToAdd,
setCommittedFieldsToAdd,
] = React.useState(0);
return (
<div>
<div>
<label>Number of fields to add</label>
<input
type="number"
value={inputfieldsToAdd}
onChange={(e) =>
setInputfieldsToAdd(
parseInt(e.currentTarget.value, 10)
)
}
/>
</div>
<button
onClick={() => {
setCommittedFieldsToAdd(
inputfieldsToAdd
);
}}
>
Add fields
</button>
{/* TODO - add the dynamic fields */}
</div>
);
我们也有一个Field 组件:
const Field = ({ id }: { id: number }) => (
<div>
<label htmlFor={`field${id}`}>Field {id}</label>
<input id={`field${id}`} type="text" />
</div>
);
因此,我们需要渲染Field ,次数由用户定义。
一个解决方案
我们可能会想到使用JSX中的for 循环,因为当我们需要做某件事情n次时,通常会使用这种方式:
{
for (
let i = 1;
i <= committedFieldsToAdd;
i++
) {
<Field id={i} key={i} />;
}
}
...但是这在JJSX中并不直接起作用,因为for 循环并不返回任何可以添加到DOM中的东西。
我们可以在JJSX之外使用一个for 循环来构建字段元素,然后在JJSX中输出字段元素:
const fields: JSX.Element[] = [];for (let i = 1; i <= committedFieldsToAdd; i++) { fields.push(<Field id={i} key={i} />);}
return (
<div>
...
<button
...
>
Add fields
</button>
{fields} </div>
);
这也是可行的,但还有一个更简洁的解决方案。
一个更简明的解决方案
通常情况下,我们在JJSX中迭代时在数组上使用map 方法。我们怎样才能创建一个有适当数量的数组,让我们可以映射过去?好吧,我们可以使用Array 构造函数,输入要创建的元素数量:
Array(committedFieldsToAdd);
但我们不能映射,因为这些元素是空的。所以,我们可以做的一个技巧是将数组分散到一个新的数组中:
[...Array(committedFieldsToAdd)];
然后,这可以被映射到输出字段上,如下所示:
[
...Array(committedFieldsToAdd),
].map((value: undefined, index: number) => (
<Field id={index + 1} key={index} />
));
map 方法的第一个参数是数组元素的值,也就是undefined 。数组索引是第二个参数,它对我们更有用。所以,我们使用数组索引来形成React元素键和字段ID。
很好!
在下面的CodeSandbox链接中可以看到一个工作实例。