Skip to main content

Що таке іммутабельність стану?

Що таке іммутабельність стану

Іммутабельність (immutability) - це принцип, при якому об'єкти або масиви не змінюються напряму, а при зміні створюється нова копія з потрібними змінами.

Тобто: замість того щоб "виправити старе" -> створюємо "нове зі змінами".


Приклад без іммутабельності (погано)

javascript
const [user, setUser] = useState({ name: "Alex", age: 25 }); // мутуємо об'єкт напряму user.age = 26; setUser(user);

Тут ти змінив той самий об'єкт у пам'яті, не створюючи новий. React не помітить різниці, тому що посилання на об'єкт лишилося тим самим. -> Ререндер не відбудеться.


Приклад з іммутабельністю (правильно)

javascript
setUser(prev => ({ ...prev, age: 26 }));

Тепер React бачить, що user вказує на новий об'єкт у пам'яті і розуміє, що стан змінився -> викликає перемальовування.


Чому React вимагає іммутабельного оновлення

Тому що React не порівнює вміст об'єктів - він порівнює посилання.


React працює за принципом shallow compare (поверхневе порівняння)

javascript
oldState === newState

Він не заглядає всередину об'єктів і масивів. Якщо посилання лишилося тим самим - React вирішує, що нічого не змінилося. Якщо посилання нове - React вважає, що потрібно оновити UI.


Приклад: посилання і значення

javascript
const a = { x: 1 }; const b = a; // посилання на той самий об'єкт const c = { x: 1 }; // новий об'єкт з тим самим вмістом console.log(a === b); // true console.log(a === c); // false

React реагує на зміну посилання (адреси), а не на однакові "внутрішні значення".


Що ламається при мутації

Якщо ти мутуєш стан напряму:

  1. React не дізнається про зміну -> не буде ререндера.
  2. Передбачуваність порушується - старі версії стану змінюються "по ланцюжку".
  3. Оптимізації React ламаються (наприклад, memo, PureComponent).
  4. Відлагодження і "time-travel" (у devtools) стають неможливими, тому що минулі стани вже зіпсовані.

Приклад з масивом

Погано:

javascript
setItems(items.push("новий")); // push мутує масив

Добре:

javascript
setItems([...items, "новий"]); // створює новий масив

Тепер React побачить, що посилання на масив змінилося, і оновить компонент.


Коли це особливо важливо

Іммутабельність потрібна:

  • при роботі з об'єктами і масивами (складні стани);
  • у Redux, Zustand, Jotai, Recoil - усі ці бібліотеки тримаються на ній;
  • при використанні мемоізації (React.memo, useMemo, useCallback);
  • при оптимізації ререндерів.

Під капотом: чому це зручно React

Іммутабельність дає React можливість:

  • швидко розуміти, які частини дерева змінилися (через порівняння посилань);
  • ефективно виконувати reconciliation (узгодження);
  • безпечно "перемотувати" стан у devtools;
  • спрощувати оптимізації (shouldComponentUpdate, React.memo, useMemo і т.д.).

Підсумок

ПитанняВідповідь
Що таке іммутабельність?Дані не змінюються напряму, а замінюються новою копією
Чому React її вимагає?React порівнює посилання, а не вміст об'єктів
Що буде при мутації?React не помітить змін і не перемалює компонент
Як оновлювати правильно?Створювати новий об'єкт/масив зі змінами
ПрикладsetUser(prev => ({ ...prev, name: "Tim" }))

Проста аналогія

Мутація - це "перемалювати стару картину поверх старою фарбою". Іммутабельність - це "зробити нову копію картини зі змінами".

React бачить тільки нову картину, тому розуміє, що потрібно оновити екран.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.