>想象一下我有这个对象数组
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 中那样给元素一个通用唯一的键,React 会优化一些东西吗?还是在两种情况下它的行为相同?
选项#1:
- 无论如何,密钥都是唯一的 ID
- 同一元素始终在每次渲染时获得相同的 ID
选项#2:
- 键在
filteredList
上始终是唯一的,但相同的元素可能会使用与先前渲染不同的键重新渲染。
注意:如果您未设置任何密钥,则会收到警告:
警告:列表中的每个孩子都应该有一个唯一的"钥匙"道具。有关详细信息,请参阅 https://reactjs.org/docs/lists-and-keys.html#keys。
如果数据具有自然的唯一 ID,则应将其用作键。
如果您的数据没有自然 ID,则在满足以下所有条件的情况下,您可以使用索引作为键:
- 列表和项目是静态的 - 它们不会计算也不会更改
- 列表中的项没有 ID
- 列表永远不会重新排序或筛选。
源
如果数据没有自然 ID,并且需要更改列表,则可以向模型添加新的 ID 属性或对内容的某些部分进行哈希处理以生成密钥。密钥只需要在其同级中是唯一的,而不是全局唯一的。
源
来自官方文档:
https://reactjs.org/docs/lists-and-keys.html
当呈现项没有稳定的 ID 时,可以使用项索引作为键作为最后的手段。如果项的顺序可能更改,我们不建议对键使用索引。这可能会对性能产生负面影响,并可能导致组件状态问题。
正如我在评论中所说:
原因是如果你的过滤器发生了变化,并且现在位于索引 2 的项目与以前位于索引 2 的项目不同,那么 React 就会感到困惑,而不是在那里渲染一个新的组件,它只会改变它发送组件的道具——而且它可能根本不会在视觉上更新,这取决于你如何编码它。
我肯定在个人之前使用索引作为键遇到了问题