当不映射数组时,我们需要为孩子设置键吗?

时间:2018-06-28 10:36:46

标签: reactjs

想象一下我们有这个JSX:

<App>
  <Counter value={this.state.counter1} />
  <Counter value={this.state.counter2} />
</App>

我们也有这个(想象this.state.counters是一个值数组):

<App>
  { this.state.counters.map((value, i) => <Counter value={value} key={i} /> )}
</App>
  1. 为什么我们需要在第二个示例中为每个Counter设置一个键,而不是在第一个示例中?渲染是否基本相同?
  2. 您认为这两种方法中的哪一种在性能上都更好,将所有计数器值都放在一个数组中或为每个计数器使用一个键?

1 个答案:

答案 0 :(得分:4)

  

为什么我们需要在第二个示例中为每个Counter设置一个键,而不是在第一个示例中?渲染基本不一样吗?

是的,结果是相同的。

在第一种情况下,React已经知道组件的顺序,因为您已经在代码中定义了它的顺序。

在第二种情况下,组件的顺序完全取决于数组的定义方式。 React无法仅通过知道要迭代哪个数组来知道这一点。如果数组曾经被更改过(移除,添加或更改了项目),React应该如何知道一个组件是应该使用新的props进行更新还是仅仅更改其顺序?

考虑以下示例:

const arr = [{id: 1, name: 'Chris'}, {id: 2, name: 'Emi'}];

<App>
  {arr.map(x => <Component name={x.name} id={x.id} />)}
</App>

这将产生与以下结果相同的结果:

<App>
  <Component id={1} name="Chris" />
  <Component id={2} name="Emi" />
</App>

但是,如果将数组更改为:

const arr = [{id: 1, name: 'Emi'}, {id: 2, name: 'Chris'}];

我们是将Chris重命名为Emi,还是将Emi重命名为Chris,还是只交换位置? React无法“自动”知道这一点。

由于这个原因,我们定义了一个key道具,该道具告诉React如何建模您的数据。如果我们在这里将键定义为name,React会将其解释为展示位置交换。如果是id,React将更新道具。

奖励情况:如果我们将密钥定义为id,并且将{id: 1, name: 'Chris'}更改为{id: 3, name: 'Chris'},则相应的组件将卸载,并且换成新的(而不是道具更新!)。为什么?因为具有身份 1的组件不再存在。

有关键的更多信息:Understanding unique keys for array children in React.js


  

您认为这两种方法中的哪一种在性能上都更好,将所有计数器值都放在一个数组中或为每个计数器使用一个键?

我认为任何性能差异都可以忽略不计。 “正确”的方式更多地取决于偏好,这对于您作为程序员来说是有意义的。通常,出于可读性考虑,如果要重复渲染相同的组件但使用不同的道具,请映射一个数组。另外,如果您有许多组件,则将它们保留在数组中更有意义。