列表中React元素的最佳键是什么?

时间:2019-12-20 12:20:47

标签: javascript reactjs react-hooks

想象一下我有这个对象数组

fullList = [
  {label: "item A", id="itemA", someBool: true}, 
  {label: "item B", id="itemB", someBool: true}, 
  {label: "item C", id="itemC", someBool: true}, 
  {label: "item D", id="itemD", someBool: false}, 
  {label: "item E", id="itemE", someBool: false},
];

但是我没有在屏幕上呈现完整列表。我正在根据一些过滤器值对其进行过滤,并呈现了一个过滤后的列表。

用户与过滤器进行交互,并将根据他/她选择的过滤器看到不同的过滤列表。

然后,我有两个键选项:

const filteredList = fullList.filter((item) => item.someBool === true);

const filteredListItems = filteredList.map((item,index) => 
  <Item_UI_Component
    key={item.id}          // OPTION #1 - THIS IS ONLY POSSIBLE IF THE FULL LIST CONTAINS id's
    key={index}            // OPTION #2 - THIS IS ALWAYS POSSIBLE
    ...SOME OTHER PROPS
  />
);

问题

两种方法的实际区别是什么?我会和他们中的任何一个一起得失吗?如果我像选项#1中那样给元素一个UNIVERSALLY唯一键,React会优化某些东西吗?还是两种情况下的行为都一样?

选项1:

  • 无论如何,密钥都是唯一的ID
  • 同一元素在每个渲染器上始终具有相同的ID

选项2:

  • 该键在filteredList上始终是唯一的,但是可以使用与上一个渲染器不同的键重新渲染同一元素。

注意:如果您未设置任何键,则会收到警告:

  

警告:列表中的每个孩子都应该有一个唯一的“关键”道具。有关更多信息,请参见https://reactjs.org/docs/lists-and-keys.html#keys

2 个答案:

答案 0 :(得分:1)

摘自官方文档:

https://reactjs.org/docs/lists-and-keys.html

  

当您没有呈现项目的稳定ID时,可以将项目索引用作最后的选择。如果项目的顺序可能更改,我们不建议使用索引作为键。这可能会对性能产生负面影响,并可能导致组件状态出现问题。

正如我在评论中所说:

原因是因为如果您的过滤器发生变化,并且现在位于索引2处的项目与以前位于索引2处的项目不同,则存在非常真实的风险,即React会变得混乱而不是呈现一个新的组件,它将只更改发送该组件的道具,并且根据您的编码方式,它可能根本不会在视觉上进行更新。

使用索引作为键之前,我肯定遇到了问题

答案 1 :(得分:1)

如果您的数据具有自然的唯一ID,则应将其用作密钥。

如果您的数据没有自然ID,则如果满足以下所有条件,则可以将索引用作键:

  1. 列表和项目是静态的-它们不会计算且不会更改
  2. 列表中的项目没有ID
  3. 列表从不重新排序或过滤。

Source

如果数据没有自然ID,并且您需要更改列表,则可以向模型添加新的ID属性,或对内容的某些部分进行哈希处理以生成密钥。密钥只必须在其兄弟姐妹之间唯一,而不是全局唯一。

Source