React 中 key 的作用是什么?为什么不能用 index 做 key?

key 的作用

key 是 React Diff 算法识别列表项的唯一标识,帮助 React 判断哪些元素变化了。

Diff 过程

React 将新旧虚拟 DOM 对比:

  1. 相同 key 的元素视为同一项,复用 DOM 节点
  2. 不同 key 的元素视为不同项,销毁重建
  3. key 不变但位置变化,只移动 DOM 而不重建

为什么不能用 index 做 key

场景:列表头部插入新元素

// 初始列表
// index 0: 'Apple'
// index 1: 'Banana'
// index 2: 'Cherry'

// 头部插入 'Orange'
// index 0: 'Orange' ← key 没变但内容变了
// index 1: 'Apple'  ← key 没变但内容变了
// index 2: 'Banana' ← key 没变但内容变了
// index 3: 'Cherry' ← 新增

React 认为前 3 个 key 没变,会复用它们的 DOM 节点并更新内容。所有元素都需要重新渲染,而不是只渲染新元素。

正确做法

// ✅ 用唯一 ID 做 key
{items.map(item => <Item key={item.id} data={item} />)}

index 做 key 导致的 bug

1. 输入框错位

// 列表项包含输入框,头部插入新项时,输入框内容会跟着错位
{items.map((item, index) => (
  <div key={index}>
    <input defaultValue={item.value} />
  </div>
))}
// 第一个输入框的内容会变成第二个的

2. 动画异常

// CSS transition 基于 DOM 元素身份,index 做 key 会导致动画绑定到错误元素

3. 组件状态混乱

// 有状态的子组件,状态会绑定到错误的列表项
{items.map((item, index) => (
  <ExpandableItem key={index} data={item} /> // 展开状态会错位
))}

什么时候可以用 index

// 静态列表可以用 index
{staticOptions.map((opt, i) => <option key={i}>{opt}</option>)}

总结

同分类其他题目