Пошук уроків, статей та іншого контенту
Рендеринг масивів через map() та чому key критично важливий для правильного оновлення.
Щоб показати масив даних як список елементів UI, використовують звичайний метод масивів map(), що перетворює кожен елемент даних на JSX-елемент — жодного спеціального «циклу» в JSX не існує, це той самий map(), який уже знайомий із основного курсу JavaScript:
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}key — спеціальний prop (не передається всередину самого компонента), який допомагає React зрозуміти, який DOM-вузол відповідає якому елементу масиву даних між рендерами. Без стабільного key React порівнює елементи списку позиційно, тому додавання елемента на початок масиву змушує React вважати, що змінились усі елементи списку, хоча насправді змінилась лише одна позиція — детальніше механізм порівняння дерев розібраний у статті «Що таке Virtual DOM і навіщо він потрібен».
// Погано — index як key: React плутає "елемент зсунувся" зі "елемент змінився"
{todos.map((todo, index) => (
<TodoItem key={index} todo={todo} />
))}
// Добре — стабільний унікальний id самого елемента даних
{todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} />
))}Якщо список гарантовано статичний — ніколи не сортується, не фільтрується, елементи не додаються й не видаляються всередині, а не лише в кінці — index як key не створює проблем. Але оскільки такі гарантії легко порушити пізнішою зміною коду, а стабільний id зазвичай уже є в даних, за замовчуванням варто одразу використовувати саме id.
key вказують на найзовнішньому елементі, що повертається всередині map(), — а не десь глибоко всередині дочірнього компонента. Якщо map() повертає компонент, key ставиться саме на використанні цього компонента:
// key на компоненті, а не всередині нього
{users.map((user) => (
<UserCard key={user.id} user={user} />
))}index масиву як key для списків, що можуть переупорядковуватись, фільтруватись чи змінювати склад — призводить до втрати стану полів вводу, неправильних анімацій, показу застарілих даних у неправильному DOM-вузлі.
Використання Math.random() чи Date.now() як key — генерує нове значення на кожному рендері, тому React щоразу вважає всі елементи новими й перестворює весь список, що гірше навіть за index.
Попередження React у консолі «Each child in a list should have a unique key prop» проігнороване як несуттєве — це прямий сигнал про потенційні баги з рендерингом списку, а не стилістична причіпка.
Списки в React рендеряться звичайним map(), а key — спосіб сказати React, який DOM-вузол відповідає якому елементу даних між оновленнями. Стабільний, унікальний ідентифікатор із самих даних (id) — правильний вибір за замовчуванням; index масиву прийнятний лише для гарантовано статичних списків, а Math.random()/Date.now() неприйнятні ніколи.