如何在React中用JSX输出一个元素n次

606 阅读2分钟

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

Repeating elements n times

一个例子

这里有一个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链接中可以看到一个工作实例。

codesandbox.io/s/repeat-el…