为什么在 React 中使用索引(Index)作为 Key 是个坏主意
你在 React 中构建了一个动态列表。你删除了一个项目。突然间,另一个项目的 UI 状态发生了变化。或者,你对列表进行了排序,结果输入的数据出现在了错误的组件中。
发生这种情况是因为你使用了数组索引作为 key。
React 使用一种称为虚拟 DOM(Virtual DOM)的系统来更新你的 UI。当状态发生变化时,React 会将新树与旧树进行比较。这个过程被称为协调(reconciliation)。
key 属性就像是组件的身份证。它告诉 React:
- 哪个项目发生了变化。
- 哪个项目是新增的。
- 哪个项目被删除了。
如果你使用索引作为 key,就会产生问题。数组是动态的。当你添加、删除或重新排序项目时,索引就会发生变化。
以下是失效的原因:
性能问题 如果你在列表开头插入一个项目,其后的每一个项目都会获得一个新的索引。React 会认为每个项目都发生了变化,从而重新渲染整个列表,而不是仅重新渲染新增的项目。
状态 Bug 这是最危险的部分。如果你的列表项包含内部状态(例如输入框或复选框),索引会导致 Bug。
想象一下,你在第一个任务的输入框中输入了 "Important"。然后你删除了该任务。如果你使用索引作为 key,React 会发现索引 0 仍然存在,于是它会复用旧的组件。现在,你的 "Important" 文本就会出现在第二个任务的输入框中。
正确做法:
- 使用数据库 ID:始终使用数据库中的唯一 ID(例如
_id或id)。 - 在前端生成 ID:如果你没有数据库,可以使用
uuid或nanoid等库。 - 使用浏览器 API:使用
window.crypto.randomUUID()这种内置方式来创建唯一 ID。
什么时候可以安全地使用索引? 只有当你的列表满足以下三个规则时才可以:
- 列表是静态的(不添加或删除项目)。
- 列表从不重新排序(不进行排序或过滤)。
- 项目没有内部状态(没有输入框或复选框)。
停止使用索引作为 key,以保持你的应用快速且无 Bug。
