MST
星途 面试题库

面试题:复杂场景下React Keys的使用策略

在一个复杂的React应用中,有一个多层嵌套的列表结构,且列表项之间存在动态增删改查操作。在这种场景下,如何合理地选择和生成key以确保应用的性能和渲染的准确性?请结合实际案例说明可能遇到的问题及解决方案。
27.9万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

合理选择和生成 key 的方法

  1. 使用唯一标识:如果列表项数据本身带有唯一标识,如数据库中的 id,应优先使用它作为 key。例如,一个待办事项列表,每个待办事项都有一个唯一的 todoId,则可以这样设置 key
const todos = [
  { todoId: 1, text: 'Learn React' },
  { todoId: 2, text: 'Build a project' }
];

const TodoList = () => (
  <ul>
    {todos.map(todo => (
      <li key={todo.todoId}>{todo.text}</li>
    ))}
  </ul>
);
  1. 生成临时唯一标识:若数据本身没有唯一标识,可以生成临时的唯一标识。比如使用 uuid 库生成通用唯一识别码(Universally Unique Identifier)。
import { v4 as uuidv4 } from 'uuid';

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

const ItemList = () => (
  <ul>
    {items.map(item => (
      <li key={uuidv4()}>{item.name}</li>
    ))}
  </ul>
);

可能遇到的问题

  1. 使用索引作为 key:如果使用数组索引作为 key,在进行列表项增删操作时会导致性能问题和渲染不准确。例如,有一个任务列表,通过索引设置 key
const tasks = [
  { taskName: 'Task 1' },
  { taskName: 'Task 2' }
];

const TaskList = () => (
  <ul>
    {tasks.map((task, index) => (
      <li key={index}>{task.taskName}</li>
    ))}
  </ul>
);

当在列表开头添加一个新任务时,原来的任务索引会改变,React 会认为所有列表项都发生了变化,从而重新渲染整个列表,而不是只更新新增的项,这会造成不必要的性能开销。并且,如果列表项有状态,如输入框的内容,由于 key 改变,React 会销毁并重新创建组件,导致输入框内容丢失。

  1. key 不唯一:若生成的 key 不唯一,React 会发出警告,并且可能导致渲染出现混乱。例如,错误地重复使用了相同的 key
const data = [
  { value: 'A' },
  { value: 'B' }
];

const BadList = () => (
  <ul>
    {data.map(() => (
      <li key="sameKey">Some item</li>
    ))}
  </ul>
);

解决方案

  1. 避免使用索引作为 key:始终优先使用数据的唯一标识或生成临时唯一标识,如上述使用 iduuid 的方式。
  2. 确保 key 的唯一性:仔细检查生成 key 的逻辑,保证每个列表项都有独一无二的 key。在使用第三方库生成 key 时,确认库的使用方法正确,避免重复生成相同的 key