Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Junior Хуки

Як оновлювати вкладені об'єкти й масиви у стані React без мутацій?

React вирішує, чи перерендерити компонент, порівнюючи посилання: новий стан має бути новим об'єктом. Зміна старого об'єкта «на місці» не помітна для React - і ламає логіку порівняння в memo, useEffect, useMemo.

Об'єкти - копія з розгортанням:

const [user, setUser] = useState({ name: 'Оля', address: { city: 'Київ', street: '' } });

// неправильно: мутація
user.address.city = 'Львів';
setUser(user);

// правильно: нові об'єкти на кожному рівні шляху до зміни
setUser({
  ...user,
  address: { ...user.address, city: 'Львів' },
});

Розгортання (...) поверхневе - копіювати треба кожен рівень, що змінюється.

Масиви - методи, що повертають новий масив:

Дія Замість мутації Без мутації
додати push, unshift [...items, item]
видалити splice items.filter((i) => i.id !== id)
змінити items[i] = x items.map((i) => (i.id === id ? { ...i, done: true } : i))
вставити splice [...items.slice(0, n), item, ...items.slice(n)]
сортувати sort, reverse items.toSorted(...), items.toReversed()

Пастка зі «скопійованим» масивом: [...items] копіює масив, але елементи-об'єкти лишаються ті самі. copy[0].done = true змінює об'єкт і в старому стані.

Глибоко вкладений стан робить такі оновлення громіздкими. Два виходи:

  • Immer (use-immer): пишете «мутацію», а бібліотека створює новий незмінний об'єкт:
updateUser((draft) => {
  draft.address.city = 'Львів';
});
  • сплощити стан - зберігати сутності за id в окремих полях замість глибокої вкладеності.

Функціональне оновлення для залежності від попереднього стану: setItems((prev) => [...prev, item]).

Чому це важливо не лише для рендеру: незмінність дає «знімки» історії (скасування дій), дешеве порівняння для оптимізацій і передбачувані ефекти.

Докладніше в документації: Оновлення об'єктів у стані

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання