Key 到底有什么用?

面试必问,这篇文章给你讲明白

先说结论:Key 就是 React 用来识别列表元素身份的"身份证"。

Key 的作用

React 的 Diff 算法靠 Key 来判断元素是"新建了"、"删除了"还是"移动了":

  • Key 不存在 → 新建
  • Key 消失了 → 删除
  • Key 还在但位置变了 → 移动

如果没有 Key,React 就没办法知道元素到底啥情况,只能傻傻地逐个对比更新——性能差,还容易出 bug。

为什么不能用 index?

静态列表可以用 index,如果你的列表永远不增不减不排序,那用 index 完全没问题。

但如果列表会变化,问题就来了:

头部插入数据

// 原来的列表
[A, B, C][ // index: 0, 1, 2
  // 在头部插入 New
  (New, A, B, C)
]; // index: 0, 1, 2, 3

React 发现:

  • index=0 的组件还在(其实是 A 被复用成了 New)→ 内容改成 New
  • index=1 的组件还在(其实是 B 被复用成了 A)→ 内容改成 A
  • index=2 的组件还在(其实是 C 被复用成了 B)→ 内容改成 B
  • C 被判断为新增

结果:所有组件都被更新了一遍,性能炸裂。

状态错乱

如果列表项里有非受控组件(比如输入框):

items.map((item, index) => <input key={index} defaultValue={item.name} />);

当你在中间插入一项时,输入框的内容会"跑错位置"——因为 React 复用了组件实例,状态也一起带过去了。

正确用法

用 ID(推荐)

items.map((item) => <Item key={item.id} {...item} />);

来自数据库的唯一 ID,永远不变,最靠谱。

生成的 Hash

如果数据没有 ID,可以根据内容生成一个唯一标识(前提是内容本身不重复):

items.map((item) => <Item key={generateHash(item)} {...item} />);

万不得己才用 index

// 纯展示的静态列表,可以用 index
items.map((item, index) => <div key={index}>{item.name}</div>);

总结

场景Key 怎么选
数据库数据item.id
动态生成用 Hash
静态列表可以用 index

记住:列表会变就用 ID,别偷懒用 index,不然后面有你好受的。