Переклад:
Фото: Aadil Imam Hussain на Unsplash
Нещодавно я працював із списками в React і зіткнувся з проблемою, яка спочатку не здавалася великою. Але коли я заглибився в деталі, я зрозумів, наскільки важливо використовувати правильні ключі в React. Щось таке просте, як використання неправильного ключа, наприклад індексу, може викликати дивні помилки і непередбачувану поведінку.
Вступ
У React, при відображенні списків елементів, кожен елемент повинен мати унікальний пропс key
. Цей ключ допомагає React визначити, які елементи змінилися, були додані або видалені, що дозволяє оптимізувати рендеринг і ефективно оновлювати DOM. Однак використання неправильних ключів, таких як індекси масиву, може призвести до різних проблем.
У цьому блозі я поділюсь своїм досвідом, проблемами, з якими я стикався, і як уникнути їх, слідуючи найкращим практикам.
Зустріч із проблемою
Я працював над простим додатком React, який дозволяв користувачам додавати елементи до списку. Ось початковий код:
import { useState } from "react";
import "./App.css";
function App() {
const [items, setItems] = useState([]);
const [input, setInput] = useState("");
const handleAddItem = () => {
if (input === "") return;
setItems([input, ...items]);
setInput("");
};
return (
<>
Item List
setInput(e.target.value)} placeholder="Enter item" data-testid="input-field" /> Add Item
{items.map((item, index) => (
{item}
))}
); } export default App; ```
## Проблема
Спочатку все працювало добре. Однак, коли я запустив свої тести, вони не пройшли. Проблема була тонкою, але значною: я використовував індекс масиву як ключ для кожного елемента списку. Коли нові елементи додавалися на початок масиву, індекси існуючих елементів змінювались, що призводило до того, що React неправильно інтерпретував, які елементи змінилися, були додані чи видалені.
## Конкретні проблеми, з якими я зіткнувся
1. **Невірне оновлення DOM**: React може видаляти і переробляти елементи замість того, щоб їх оновити, що призводить до втрати стану компонента, такого як значення введення або фокус.
2. **Глюки анімацій**: Якщо анімації прив’язані до елементів списку, вони можуть перезапускатись або поводитись непередбачувано, оскільки React думає, що елементи були видалені і знову додані.
3. **Проблеми з продуктивністю**: Непотрібні повторні рендери та маніпуляції з DOM можуть знижувати продуктивність, особливо при великих списках.
## Приклад сценарію
Розглянемо наступну послідовність операцій:
1. Початковий стан: `items = []`
2. Додати "Item 1": `setItems(["Item 1", ...items])` результат: `items = ["Item 1"]`
3. Додати "Item 2": `setItems(["Item 2", "Item 1"])` результат: `items = ["Item 2", "Item 1"]`
У цьому випадку ключі для елементів — це їх індекси:
- "Item 1" спочатку має ключ `0`
- Після додавання "Item 2", "Item 1" тепер має ключ `1`
React може інтерпретувати це як:
- Елемент з ключем `0` ("Item 1") було видалено.
- Новий елемент з ключем `0` ("Item 2") було додано.
- Новий елемент з ключем `1` ("Item 1") було додано.
## Потенційні проблеми
1. **Втрати стану введення**: Якщо у вас є поле введення в кожному елементі списку, стан введення може бути втрачений, коли ключ змінюється. Наприклад, якщо користувач вводить текст у поле введення в "Item 1", і "Item 2" додається, поле введення може втратити фокус або його значення буде скинуто.
2. **Глюки анімацій**: Якщо у вас є анімації, прив’язані до елементів списку, вони можуть перезапускатись або поводитись непередбачувано, оскільки React думає, що елементи були видалені і знову додані.
3. **Проблеми з продуктивністю**: Непотрібні повторні рендери та маніпуляції з DOM можуть призвести до зниження продуктивності, особливо при великих списках.
## Рішення: Використання унікальних ідентифікаторів
Щоб уникнути цих проблем, найкраще використовувати унікальні та стабільні ключі для елементів списку.
Ось покращена версія коду з використанням унікальних ідентифікаторів:
import { useState } from "react";
import "./App.css";
function App() {
const [items, setItems] = useState([]);
const [input, setInput] = useState("");
const handleAddItem = () => {
if (input === "") return;
setItems([...items, { id: Date.now(), text: input }]);
setInput("");
};
return (
<>
Item List
setInput(e.target.value)} placeholder="Enter item" data-testid="input-field" /> Add Item
{items.map((item) => (
{item.text}
))}
); } export default App; ```
У цій версії кожен елемент має унікальний id
, згенерований за допомогою Date.now()
, що забезпечує стабільність і унікальність ключів, запобігаючи проблемам з повторними рендерами та покращуючи загальну стабільність компонента.
Кращі практики для ключів
- Використовуйте унікальні ідентифікатори: Завжди використовуйте унікальні та стабільні ключі для елементів списку. Уникайте використання індексів як ключів.
- Послідовність: Забезпечте, щоб ключі залишались незмінними при повторних рендерах, щоб уникнути непотрібних оновлень DOM.
- Продуктивність: Правильні ключі допомагають React оптимізувати рендеринг і покращують продуктивність, особливо з великими списками.
Висновок
Використання правильних ключів у списках React є важливим для підтримки стабільності та продуктивності вашого додатка. Простенькі помилки, як використання індексів масиву як ключів, можуть призвести до значних проблем, таких як неправильні оновлення DOM, втрата стану компонента та зниження продуктивності. Дотримуючись кращих практик і використовуючи унікальні ідентифікатори, ви можете уникнути цих проблем і забезпечити, щоб ваші компоненти React працювали так, як очікується.
Сподіваюся, цей блог допоміг вам зрозуміти важливість ключів у списках React і як уникнути поширених помилок.
Щасливого кодування!👩💻👨💻
Дякуємо, що стали частиною нашої спільноти
Перш ніж піти:
- Не забудьте плескати та підписуватися на автора ️👏️️
- Слідуйте за нами: X | LinkedIn | YouTube | Newsletter | Podcast
- Ознайомтесь із CoFeed, розумним способом залишатися в курсі останніх новин про технології 🧪
- Запустіть свій безкоштовний блог з підтримкою AI на Differ 🚀
- Приєднуйтесь до нашої спільноти контент-створювачів на Discord 🧑🏻💻
- Для більшого контенту відвідайте plainenglish.io + stackademic.com
Перекладено з: Using Index as Key in React/Next.js? You’re Inviting Bugs to Your Code🐞