返回

释放 React 的潜力:避免使用 index 作为 key

前端

在 React 中使用索引作为键的陷阱

在 React 中,使用键来唯一识别列表中的元素至关重要。如果没有键,React 无法确定哪些元素已更改,从而导致不必要的重新渲染和性能问题。然而,使用索引作为键会带来一些严重的陷阱,可能会给您的应用程序带来麻烦。

为什么不推荐使用索引作为键?

  • 列表项重新排序时容易出错: 当列表项重新排序时,它们的索引也会改变。这会导致 React 将它们识别为不同的元素,从而触发不必要的重新渲染。
const list = ['Item 1', 'Item 2', 'Item 3'];

// 使用索引作为键
const ItemList = () => {
  return (
    <ul>
      {list.map((item, index) => <li key={index}>{item}</li>)}
    </ul>
  );
};

// 重新排序列表项
list.sort((a, b) => a.localeCompare(b));

// React 将重新渲染所有列表项,因为它们的索引已更改
  • 元素删除后容易出错: 当删除列表项时,其后续项的索引也会改变。这会导致 React 错误地认为后续项已经更改,再次触发重新渲染。
const list = ['Item 1', 'Item 2', 'Item 3'];

// 使用索引作为键
const ItemList = () => {
  return (
    <ul>
      {list.map((item, index) => <li key={index}>{item}</li>)}
    </ul>
  );
};

// 删除列表项
list.splice(1, 1);

// React 将错误地重新渲染列表项 2 和 3,因为它们的索引已更改
  • 与真实世界的状态脱节: 索引与列表项本身的状态无关。这可能会导致混淆和难以调试。
const list = [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, { id: 3, name: 'Item 3' }];

// 使用索引作为键
const ItemList = () => {
  return (
    <ul>
      {list.map((item, index) => <li key={index}>{item.name}</li>)}
    </ul>
  );
};

// 更新列表项的状态
list[1].name = 'Updated Item 2';

// React 不会重新渲染列表项 2,因为它的索引未更改

更好的选择

为了避免这些陷阱,请考虑使用以下更好的选择作为键:

  • 元素 ID: 如果列表项具有唯一的 ID,这是理想的选择。
  • UUID(通用唯一识别码): 如果列表项没有 ID,可以使用 UUID 来生成唯一的键。

示例

使用元素 ID 作为键:

const list = [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, { id: 3, name: 'Item 3' }];

// 使用元素 ID 作为键
const ItemList = () => {
  return (
    <ul>
      {list.map(item => <li key={item.id}>{item.name}</li>)}
    </ul>
  );
};

// 重新排序列表项或删除列表项
// React 将正确识别已更改的元素并仅重新渲染它们

使用 UUID 作为键:

const list = [{ name: 'Item 1' }, { name: 'Item 2' }, { name: 'Item 3' }];

// 使用 UUID 作为键
const ItemList = () => {
  return (
    <ul>
      {list.map(item => <li key={uuid()}>{item.name}</li>)}
    </ul>  );
};

// 重新排序列表项或删除列表项
// React 将正确识别已更改的元素并仅重新渲染它们

结论

通过避免在 React 中使用索引作为键,您可以防止不必要的重新渲染、性能问题和调试困难。遵循最佳实践,使用元素 ID 或 UUID 作为键,确保您的应用程序高效且易于维护。

常见问题解答

  1. 为什么索引在某些情况下作为键可以正常工作?
    索引在小列表中作为键可能可以正常工作,但是当列表变得更大或元素需要重新排序时,它就会成为问题。

  2. 我还可以使用什么作为键?
    除了元素 ID 和 UUID 之外,您还可以使用字符串、数字或任何其他可以唯一标识列表项的值作为键。

  3. 使用索引作为键会导致哪些性能问题?
    随着列表的增长,React 必须为每个元素维护一个单独的键,这会增加内存消耗并降低渲染速度。

  4. 如何调试与使用索引作为键相关的问题?
    在控制台中检查 React 的警告消息,并使用 React DevTools 检查虚拟 DOM 和实际 DOM 之间的差异。

  5. 我是否可以在函数组件中使用索引作为键?
    在函数组件中,索引在组件首次渲染时是稳定的,但是如果组件重新渲染,则索引可能会改变。因此,在函数组件中使用索引作为键并不是一个好主意。