React的key

38 阅读1分钟

考虑如下代码:

function InputItem({ name }) {
  const [value, setValue] = useState("");
  return (
    <div>
      <span>{name}: </span>
      <input value={value} onChange={e => setValue(e.target.value)} />
    </div>
  );
}

function App() {
  const [list, setList] = useState([
    { id: 1, name: "Tom" },
    { id: 1, name: "Jerry" },
  ]);

  return (
    <div>
      {list.map(item => (
        <InputItem key={item.id} name={item.name} />
      ))}
    </div>
  );
}

key相同会发生什么?

首先输入框 1 输入 “A”,输入框 2 输入 “B”,然后执行setList颠倒数组的两项

你会发现两个<InputItem/>颠倒了,但是第一个输入框里还是“A”,第二个输入框里还是“B”

为什么会这样呢?

React 依赖 key 来识别哪些元素被添加、删除或修改

如果两个元素的 key 相同,React 就无法唯一标识每个节点,导致如下问题:

  • React 将两个 <InputItem> 互换
  • 发现两个节点的 key 都是 1
  • 所以虽然节点互换了,但DOM里面的状态都复用原来的位置
  • 结果是:输入框里的内容没有互换

因此key相同会发生DOM的状态错乱

那我用index作为key可以吗?下面这样:

function InputItem({ name }) {
  const [value, setValue] = useState("");
  return (
    <div>
      <span>{name}: </span>
      <input value={value} onChange={e => setValue(e.target.value)} />
    </div>
  );
}

function App() {
  const [list, setList] = useState([
    { id: 1, name: "Tom" },
    { id: 1, name: "Jerry" },
  ]);

  return (
    <div>
      {list.map((item, index) => (
        <InputItem key={index} name={item.name} />
      ))}
    </div>
  );
}

依然还是会发生原来的问题,输入框里的内容没有互换

因为互换以后index没有互换啊,还是原来的啊

现在我们知道了,不管是key相同或者用index作为key,都可能会造成DOM的状态混乱

那我不定义key会怎样,不定义keykey就都是undefined了,也会回到key相同的局面

因此我们定义key必须确保key的唯一性