Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Мутація state в reducer». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Мутувати (змінювати напряму)** `state` в reducer не можна, тому що Redux (і React) мають бачити, що стан змінився, а це можливо тільки при створенні нового об'єкта. **Ключове:** Redux і React порівнюють стан за посиланням (`===`), тому мутація об'єкта залишає посилання незмінним і компонент не оновлюється.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коротка відповідь > **Не можна мутувати (змінювати напряму)** `state` в reducer, > тому що Redux (і React) **мають бачити, що стан змінився**, > а це можливо **тільки при створенні нового об'єкта**. --- ## Детально Reducer має бути **чистою функцією**, а це означає: 1. Він **не змінює вхідні дані (state)**. 2. Він **повертає новий об'єкт**, що описує новий стан. --- ### Приклад правильного редьюсера ```javascript function counterReducer(state = { count: 0 }, action) { switch (action.type) { case 'INCREMENT': return { ...state, count: state.count + 1 } // створюємо новий об'єкт default: return state } } ``` --- ### Приклад з мутацією ```javascript function counterReducer(state = { count: 0 }, action) { switch (action.type) { case 'INCREMENT': state.count++ // мутує об'єкт return state // повертає той самий об'єкт default: return state } } ``` Проблема: Redux (і React) **не зрозуміє, що стан змінився**, оскільки **посилання на об'єкт не змінилося** - `state` залишився тим самим об'єктом у пам'яті. --- ## Чому це важливо ### 1. Redux порівнює стани за **посиланням** Redux (і React через `useSelector`) використовують **поверхневе порівняння (**`===`**)**, щоб зрозуміти, чи змінився стан. ```javascript oldState === newState // якщо true -> не перерендерюємо ``` Якщо ти мутував об'єкт, посилання залишається тим самим -> Redux думає, що нічого не змінилося -> компонент **не оновлюється**. --- ### 2. Іммутабельність дозволяє "time travel" Redux DevTools можуть "перемотувати" стан вперед-назад, тому що кожен стан зберігається як **нова версія об'єкта**. Якби редьюсери мутували `state`, старі стани просто знищувалися б. --- ### 3. Просте тестування Чисті функції легко тестувати: однакові вхідні дані -> завжди той самий результат. Якщо ти мутуєш state, результат може залежати від попереднього виклику. --- ### 4. Оптимізація React-компонентів Багато оптимізацій (наприклад, `React.memo`, `useSelector`, `PureComponent`) базуються на **порівнянні посилань** (`===`), а не на глибокому порівнянні. Іммутабельність робить це можливим. --- ## Як не мутувати state Використовуй **іммутабельні методи**: | Операція | Мутація | Іммутабельно | |---|---|---| | Додати елемент | `array.push(x)` | `[...array, x]` | | Видалити елемент | `array.splice(1,1)` | `array.filter((_, i) => i !== 1)` | | Змінити властивість | `obj.key = value` | `{ ...obj, key: value }` | | Змінити вкладений об'єкт | `state.user.name = 'Tim'` | `{ ...state, user: { ...state.user, name: 'Tim' } }` | --- ## Підсумок | Причина | Чому не можна мутувати | |---|---| | Redux порівнює за посиланням | Не побачить змін | | Time travel у DevTools | Втратяться старі стани | | Тестування | Стане непередбачуваним | | Оптимізації React | Не працюватимуть коректно | | Принцип чистих функцій | Порушується детермінізм |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.