面试题答案
一键面试Key的最佳实践经验
- 使用唯一标识作为Key:在React中,对于列表项,最好使用数据中具有唯一性的标识作为
key
。例如,在一个用户列表中,假设每个用户对象有一个唯一的id
属性。
import React from 'react';
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const UserList = () => {
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
export default UserList;
这样,当列表发生变化(如添加、删除、排序)时,React能通过key
准确识别每个列表项,高效地更新DOM。
- 避免使用索引作为Key(在大多数情况下):虽然使用索引作为
key
看起来很方便,但在列表项顺序或数量频繁变化时会出现问题。例如,我们有一个待办事项列表,最初是['任务1', '任务2', '任务3']
,索引分别为0
,1
,2
。如果删除了任务2
,任务3
的索引就会从2
变为1
,React会误以为这是任务2
的更新,而不是任务3
的重新排列,导致错误的DOM更新。
规避因Key使用不当引入的潜在陷阱
- 动态添加和删除时的问题:如果使用索引作为
key
,在动态添加或删除列表项时,会导致后面列表项的索引变化,从而使React错误地复用DOM节点。解决方法是始终使用唯一标识作为key
。例如,在一个动态添加和删除待办事项的应用中:
import React, { useState } from'react';
const TodoList = () => {
const [todos, setTodos] = useState([
{ id: 1, text: '任务1' },
{ id: 2, text: '任务2' }
]);
const [newTodoText, setNewTodoText] = useState('');
const addTodo = () => {
if (newTodoText) {
const newTodo = { id: Date.now(), text: newTodoText };
setTodos([...todos, newTodo]);
setNewTodoText('');
}
};
const deleteTodo = (todoId) => {
setTodos(todos.filter(todo => todo.id!== todoId));
};
return (
<div>
<input
type="text"
value={newTodoText}
onChange={(e) => setNewTodoText(e.target.value)}
placeholder="添加新任务"
/>
<button onClick={addTodo}>添加任务</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
<button onClick={() => deleteTodo(todo.id)}>删除</button>
</li>
))}
</ul>
</div>
);
};
export default TodoList;
- 排序时的问题:同样,排序时如果使用索引作为
key
,由于索引变化,React可能无法正确更新DOM。例如,对用户列表按年龄排序,使用唯一id
作为key
能确保React正确识别每个用户并更新DOM,如下代码:
import React, { useState } from'react';
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 20 },
{ id: 3, name: 'Charlie', age: 30 }
];
const UserSortList = () => {
const [sortedUsers, setSortedUsers] = useState(users);
const sortByAge = () => {
setSortedUsers([...sortedUsers].sort((a, b) => a.age - b.age));
};
return (
<div>
<button onClick={sortByAge}>按年龄排序</button>
<ul>
{sortedUsers.map(user => (
<li key={user.id}>{`${user.name}: ${user.age}`}</li>
))}
</ul>
</div>
);
};
export default UserSortList;
通过始终使用唯一标识作为key
,可以有效避免因key
使用不当而产生的性能问题和DOM更新错误。