面试题答案
一键面试合理选择和生成 key 的方法
- 使用唯一标识:如果列表项数据本身带有唯一标识,如数据库中的
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>
);
- 生成临时唯一标识:若数据本身没有唯一标识,可以生成临时的唯一标识。比如使用
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>
);
可能遇到的问题
- 使用索引作为 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 会销毁并重新创建组件,导致输入框内容丢失。
- key 不唯一:若生成的
key
不唯一,React 会发出警告,并且可能导致渲染出现混乱。例如,错误地重复使用了相同的key
:
const data = [
{ value: 'A' },
{ value: 'B' }
];
const BadList = () => (
<ul>
{data.map(() => (
<li key="sameKey">Some item</li>
))}
</ul>
);
解决方案
- 避免使用索引作为 key:始终优先使用数据的唯一标识或生成临时唯一标识,如上述使用
id
或uuid
的方式。 - 确保 key 的唯一性:仔细检查生成
key
的逻辑,保证每个列表项都有独一无二的key
。在使用第三方库生成key
时,确认库的使用方法正确,避免重复生成相同的key
。