Списки та ключі
These docs are old and won’t be updated. Go to react.dev for the new React docs.
These new documentation pages teach modern React and include live examples:
Для початку згадаймо, як перетворювати списки у JavaScript.
У коді, наведеному нижче, ми використовуємо функцію map()
, щоб подвоїти значення в масиві numbers
. Ми призначаємо новий масив, що повертається з map()
до змінної doubled
і виводимо її в консоль:
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);console.log(doubled);
Цей код виведе [2, 4, 6, 8, 10]
у консоль.
У React, перетворення масивів у список елементів майже ідентичне.
Рендеринг декількох компонентів
Ви можете створювати колекції елементів і включати їх у JSX за допомогою фігурних дужок {}
.
Нижче, пройдемося масивом numbers
, використовуючи функцію JavaScript map()
, і повернемо елемент <li>
у кожній ітерації. Нарешті, одержаний масив елементів збережемо у listItems
:
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) => <li>{number}</li>);
Тепер ми включимо масив listItems
цілком всередину елемента <ul>
, і будемо рендерити його у DOM:
<ul>{listItems}</ul>
Цей код виведе маркований список чисел від 1 до 5.
Простий компонент-список
Зазвичай, ви будете рендерити списки всередині якогось компонента.
Ми можемо відрефакторити попередній приклад з використанням компонента, котрий приймає масив numbers
та виводить невпорядкований список елементів.
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => <li>{number}</li> ); return (
<ul>{listItems}</ul> );
}
const numbers = [1, 2, 3, 4, 5];
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<NumberList numbers={numbers} />);
Коли ви запустите цей код, ви отримаєте попередження, що для елементів списку має бути вказано ключ. “Ключ” - це спеціальний рядковий атрибут, який потрібно вказувати при створенні списку елементів. Ми обговоримо, чому це важливо, у наступній секції.
Щоб виправити проблему з невказаними ключами, призначмо нашим елементам списку атрибут key
всередині numbers.map()
.
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
Ключі
Ключі допомагають React визначити, які елементи були змінені, додані або видалені. Ключі повинні бути надані елементам всередині масиву, щоб надати елементам стабільну ідентичність:
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number}
</li>
);
Найкращий спосіб вибрати ключ - це використати рядок, котрий буде однозначно відрізняти елемент списку від його сусідів. Найчастіше в якості ключів ви будете використовувати ID з ваших даних:
const todoItems = todos.map((todo) =>
<li key={todo.id}> {todo.text}
</li>
);
Якщо у вас немає стабільних ID для відрендерених елементів, то в крайньому випадку можна використовувати індекс елемента як ключ:
const todoItems = todos.map((todo, index) =>
// Робіть так, тільки якщо у елементів масиву немає заданого ID <li key={index}> {todo.text}
</li>
);
Ми не рекомендуємо використовувати індекси для ключів, якщо порядок елементів може змінюватися. Це може негативно вплинути на продуктивність та може викликати проблеми зі станом компонента. Почитайте статтю Робіна Покорни (Robin Pokorny), яка досконало пояснює, чому індекси-ключі призводять до проблем. Якщо ви вирішите не призначати ключ для елемента в списку, то React за замовчуванням буде використовувати індекси як ключі.
Якщо ви зацікавлені в отриманні додаткової інформації - ось детальне пояснення того, чому ключі необхідні.
Вилучення компонентів з ключами
Ключі необхідно визначати безпосередньо всередині масивів.
Наприклад, якщо ви витягаєте компонент ListItem
, то потрібно вказувати ключ для елементів <ListItem />
в масиві, замість елемента <li>
всередині самого ListItem
.
Приклад невірного використання ключів
function ListItem(props) {
const value = props.value;
return (
// Невірно! Немає необхідності визначати тут ключ: <li key={value.toString()}> {value}
</li>
);
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Невірно! Ключ необхідно визначити тут: <ListItem value={number} /> );
return (
<ul>
{listItems}
</ul>
);
}
Приклад вірного використання ключів
function ListItem(props) {
// Вірно! Тут не потрібно визначати ключ: return <li>{props.value}</li>;}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Вірно! Ключ потрібно визначати всередині масиву: <ListItem key={number.toString()} value={number} /> );
return (
<ul>
{listItems}
</ul>
);
}
Елементам усередині map()
зазвичай потрібні ключі.
Ключі повинні бути унікальними лише серед елементів конкретного масиву
Ключі, що використовуються в масиві, повинні бути унікальними тільки серед елементів цього масиву. Однак їм не потрібно бути унікальними глобально. Можна використовувати той самий ключ в двох різних масивах:
function Blog(props) {
const sidebar = ( <ul>
{props.posts.map((post) =>
<li key={post.id}> {post.title}
</li>
)}
</ul>
);
const content = props.posts.map((post) => <div key={post.id}> <h3>{post.title}</h3>
<p>{post.content}</p>
</div>
);
return (
<div>
{sidebar} <hr />
{content} </div>
);
}
const posts = [
{id: 1, title: 'Привіт, світе', content: 'Ласкаво просимо до вивчення React!'},
{id: 2, title: 'Установка', content: 'React можна встановити через npm.'}
];
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Blog posts={posts} />);
Ключі слугують підказками для React, але вони ніколи не передаються до ваших компонентів. Якщо в компоненті потрібно те ж саме значення, то передайте його явно через проп з іншим ім’ям:
const content = posts.map((post) =>
<Post
key={post.id} id={post.id} title={post.title} />
);
У наведеному вище прикладі компонент Post
може прочитати значення props.id
, але не props.key
.
Вбудовування map() у JSX
У прикладах вище ми оголосили окрему змінну listItems
та вставили її у JSX:
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => <ListItem key={number.toString()} value={number} /> ); return (
<ul>
{listItems}
</ul>
);
}
JSX дозволяє вбудувати будь-який вираз у фігурні дужки, щоб ми зуміли включити результат виконання map()
:
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) => <ListItem key={number.toString()} value={number} /> )} </ul>
);
}
Іноді це призводить до більш чистого коду, але буває і навпаки. Як і в будь-якому JavaScript-коді, вам доведеться самостійно вирішувати, чи варто витягати код в змінну заради читабельності. Майте на увазі, що якщо код всередині map()
занадто громіздкий, має сенс витягти його в окремий компонент.