Ключі (key) і рендер
React порівнює елементи списку за ключами (key), щоб розуміти, які елементи в списку залишилися тими самими, а які додалися, видалилися або помінялися місцями, і тим самим ефективно оновлювати DOM, не перестворюючи весь список.
Простіше кажучи:
Коли в тебе є список елементів (наприклад, через .map()), React має зрозуміти:
«Який із нових елементів відповідає якому старому?»
Для цього йому потрібен унікальний ідентифікатор - key. Без ключа React просто зіставлятиме елементи за позицією (0-й з 0-м, 1-й з 1-м тощо), що може призвести до несподіваних ререндерів і багів.
Приклад без ключів
function List() {
const [items, setItems] = useState(['A', 'B', 'C']);
return (
<ul>
{items.map(item => <li>{item}</li>)}
</ul>
);
}Якщо тепер поміняти масив на:
['B', 'A', 'C']React порівняє елементи за індексом:
| Старе дерево | Нове дерево | Рішення React |
|---|---|---|
| A (index 0) | B (index 0) | замінити A → B |
| B (index 1) | A (index 1) | замінити B → A |
| C (index 2) | C (index 2) | залишити |
У підсумку React видалить обидва <li> і створить нові, хоча насправді елементи просто помінялися місцями.
Приклад із ключами
<ul>
{items.map(item => <li key={item}>{item}</li>)}
</ul>Тепер React порівнює за key:
| Старе дерево | Нове дерево | Рішення React |
|---|---|---|
| key="A" | key="B" | видалити A, додати B |
| key="B" | key="A" | видалити B, додати A |
| key="C" | key="C" | залишити |
Але завдяки key React розуміє, що елементи A і B існують, просто помінялися місцями, і він не перестворює їх, а переставляє.
Чому це важливо
Без ключів React:
- втрачає зв'язок між старими і новими елементами;
- скидає стан дочірніх компонентів (наприклад, input втрачає фокус);
- виконує зайві оновлення DOM (повільніше);
- може спричинити візуальні баги (наприклад, блимання).
Як React використовує key під час diffing
Під час reconciliation (узгодження) React проходить по списку:
- Порівнює старе і нове дерево.
- Використовує key, щоб зрозуміти, чи відповідає елемент старому вузлу.
- Якщо key збігається, повторно використовує елемент (лише оновлює props).
- Якщо key новий, створює елемент.
- Якщо key зник, видаляє елемент.
Приклад зі станом у списку
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
<input type="checkbox" checked={todo.done} />
{todo.text}
</li>
))}
</ul>
);
}Якщо в кожного todo унікальний id, React:
- збереже стан checked під час перестановок;
- не перестворить увесь
<li>; - просто оновить змінені поля.
Якщо не задати ключі, то під час зміни порядку:
- React перестворить усі
<li>; - скине всі input;
- і інтерфейс «блимне».
Правила для key
| Правило | Чому |
|---|---|
| key має бути унікальним серед сусідів | Щоб React розрізняв елементи |
| Стабільний (не змінюється між рендерами) | Інакше React подумає, що елемент новий |
| Не використовувати індекс масиву як ключ | Змінюється при перестановці елементів |
| Краще використовувати унікальний id із даних | Гарантує коректну поведінку |
Підсумок
| Навіщо потрібні ключі (key) | Що робить React |
|---|---|
| Ідентифікують елементи списку | Допомагають React «зрозуміти», що змінилося |
| Прискорюють reconciliation | React оновлює лише потрібні вузли |
| Зберігають стан дочірніх компонентів | Не втрачається фокус, ввід, чекбокси тощо |
| Без ключів React порівнює за індексом | Спричиняє зайві перемальовування і баги |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.