Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Зачем нужен prop key?
key — это специальный prop в React, который помогает идентифицировать отдельные элементы в списке. Это критически важно для корректной работы компонентов при рендеринге динамических списков, так как React использует ключи для определения, какой элемент изменился, был добавлен или удалён.
Основная проблема без key
Когда React рендерит список без ключей, он использует индекс массива в качестве ключа по умолчанию. Это приводит к проблемам:
// ❌ ПЛОХО - без key
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo, index) => (
<li key={index}>
{todo.text}
</li>
))}
</ul>
);
}
Проблемы с индексом как ключом:
- При удалении элемента индексы сдвигаются, React теряет связь
- Состояние компонента привязывается к позиции, а не к данным
- Фильтрация, сортировка и переупорядочение ломают структуру
- Анимации и переходы работают неправильно
Демонстрация проблемы
// Компонент с локальным состоянием
function TodoItem({ text, initialId }) {
const [isChecked, setIsChecked] = useState(false);
return (
<li>
<input
type="checkbox"
checked={isChecked}
onChange={(e) => setIsChecked(e.target.checked)}
/>
{text}
</li>
);
}
// Использование без нормального key
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo, index) => (
<TodoItem key={index} text={todo.text} />
))}
</ul>
);
}
// ПРОБЛЕМА:
// 1. Добавили новый элемент в начало списка
// 2. React переиспользует компоненты по индексу
// 3. Состояние (isChecked) сохранилось на неправильный элемент
// 4. Чекбоксы показывают неправильные значения
Правильное использование key
// ✅ ХОРОШО - используем уникальный идентификатор
function TodoItem({ id, text }) {
const [isChecked, setIsChecked] = useState(false);
return (
<li>
<input
type="checkbox"
checked={isChecked}
onChange={(e) => setIsChecked(e.target.checked)}
/>
{text}
</li>
);
}
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo) => (
<TodoItem
key={todo.id} // Уникальный идентификатор
id={todo.id}
text={todo.text}
/>
))}
</ul>
);
}
Как работает key
React использует ключи для:
1. Идентификации элементов
// До изменения
[{ id: 1, text: 'Task 1' }, { id: 2, text: 'Task 2' }]
// После добавления в начало
[{ id: 3, text: 'Task 3' }, { id: 1, text: 'Task 1' }, { id: 2, text: 'Task 2' }]
// React понимает:
// - Элемент с id=1 переместился (был на позиции 0, стал на позиции 1)
// - Элемент с id=2 переместился (был на позиции 1, стал на позиции 2)
// - Добавился новый элемент с id=3
2. Сохранения состояния компонента
function Item({ id, value }) {
const [inputValue, setInputValue] = useState('');
return (
<div>
<input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<span>{value}</span>
</div>
);
}
// С правильным key состояние (inputValue) привязано к данным
// При переупорядочении list inputValue остаётся с правильным элементом
3. Сохранения DOM элементов
function Item({ id, value }) {
useEffect(() => {
console.log(`Item ${id} mounted`);
return () => console.log(`Item ${id} unmounted`);
}, [id]);
return <div>{value}</div>;
}
// С правильным key:
// - При сортировке/фильтрации React переиспользует DOM элементы
// - useEffect срабатывает при действительном монтировании/размонтировании
Практический пример: фильтрация списка
function User({ id, name }) {
const [isOnline, setIsOnline] = useState(false);
return (
<div className="user-card">
<h3>{name}</h3>
<button onClick={() => setIsOnline(!isOnline)}>
{isOnline ? 'Online' : 'Offline'}
</button>
</div>
);
}
function UserList() {
const [users] = useState([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
]);
const [search, setSearch] = useState('');
const filtered = users.filter(u =>
u.name.toLowerCase().includes(search.toLowerCase())
);
return (
<div>
<input
placeholder="Search..."
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
<div>
{filtered.map(user => (
<User
key={user.id} // ✅ Уникальный id, не индекс
id={user.id}
name={user.name}
/>
))}
</div>
</div>
);
}
// Без key:
// - Вводишь "Bob"
// - Видишь только User с id=2
// - Его состояние (isOnline) может быть испорчено
// - Эффекты срабатывают неправильно
// С key={user.id}:
// - Вводишь "Bob"
// - Видишь только User с id=2
// - Его состояние сохранено правильно
// - Эффекты работают корректно
Требования к хорошему key
// ✅ ХОРОШИЕ ВАРИАНТЫ:
key={item.id} // Уникальный ID из базы
key={item.uuid} // UUID генерированный на сервере
key={`${item.parentId}_${item.id}`} // Составной ключ для вложенных структур
// ❌ ПЛОХИЕ ВАРИАНТЫ:
key={index} // Индекс массива
key={Math.random()} // Random - новый ключ при каждом рендере
key={item.name} // Неуникальный (два пользователя могут быть named Alice)
Когда key не нужен
// ✅ Статический список без операций
function StaticList() {
return (
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
);
}
// ✅ Список не изменяется
const items = ['A', 'B', 'C']; // Константа
{items.map(item => <div>{item}</div>)} // key не критичен
Итоги
- key помогает React идентифицировать элементы в списках
- Без правильного key компоненты работают неправильно при изменении порядка/фильтрации
- Используй уникальный идентификатор из данных, не индекс
- Правильный key сохраняет состояние и эффекты в правильных элементах
- Это особенно важно для интерактивных компонентов с локальным состоянием