Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить Immer.js всередині Redux Toolkit?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Immer.js** всередині Redux Toolkit відповідає за **іммутабельне оновлення стану**. Він дозволяє писати код так, ніби ти мутуєш об'єкт, але **насправді створює новий, незмінний стан** за допомогою **Proxy**. **Ключове:** Immer перехоплює зміни через "чернетку" (draft) і після завершення повертає нове дерево стану, копіюючи лише змінені гілки.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коротка відповідь > **Immer.js** всередині Redux Toolkit відповідає за **іммутабельне оновлення стану**. > Він дозволяє тобі **писати код так, ніби ти мутуєш об'єкт**, > але **насправді створює новий, незмінний стан** за допомогою **Proxy**. --- ## Що відбувається при виклику `createSlice()` Коли ти пишеш редьюсер у RTK на кшталт цього: ```javascript const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment(state) { state.value++ // ← ти ніби мутуєш }, }, }) ``` RTK **не зберігає цей reducer напряму**. Під капотом він огортає твою функцію через Immer: ```javascript import { produce } from 'immer' function wrappedReducer(state, action) { return produce(state, draft => { state.value++ // ← стає "draft.value++" }) } ``` Immer бере `state`, створює для нього **"чернетку" (draft)**, дозволяє в ній робити зміни, і після завершення повертає **новий стан**, у якому змінені лише потрібні поля, а все решта - те саме (за посиланнями). --- ## Як працює `produce()` (серце Immer) Ось мінімальна реалізація "магії": ```javascript import { produce } from 'immer' const baseState = { count: 1, user: { name: 'Maria' } } const nextState = produce(baseState, draft => { draft.count++ draft.user.name = 'Alex' }) console.log(nextState) // { count: 2, user: { name: 'Alex' } } console.log(baseState) // { count: 1, user: { name: 'Maria' } } не змінився ``` --- ## Що насправді робить Immer під капотом 1. **Створює Proxy для об'єкта** `state` Кожен доступ до властивості (`get`, `set`, `delete`) перехоплюється. 2. **Запам'ятовує всі зміни, які ти зробив** Immer не змінює об'єкт одразу - він записує інструкції: ```javascript - збільшити count - змінити user.name ``` 3. **Після виходу з** `produce()` Immer створює **нове дерево стану**, копіюючи лише змінені частини. Усе, що не змінювалося, залишається **за старими посиланнями** → це дуже ефективно за пам'яттю. 4. **Повертає новий state** Новий об'єкт "чистий" і іммутабельний - його можна безпечно передавати далі в Redux. --- ## Приклад: вкладені зміни ```javascript const state = { user: { name: 'Maria', age: 25 }, settings: { theme: 'dark' } } const next = produce(state, draft => { draft.user.age = 26 }) ``` Immer: - Створює нову копію тільки гілки `user` - `settings` залишається **за тим самим посиланням** - Тому `next.settings === state.settings` → `true` Це робить оновлення **дуже продуктивними**, бо копіюється тільки змінена частина дерева. --- ## Як RTK використовує Immer всередині Redux Toolkit інтегрує Immer у `createReducer()` і `createSlice()`. Кожен редьюсер, який ти оголошуєш, фактично стає: ```javascript (state, action) => produce(state, draft => { // твій код }) ``` У RTK це робиться автоматично, тобі не потрібно явно викликати `produce()`. --- ## Приклад без RTK (чистий Redux) ```javascript function userReducer(state = { name: 'Maria', age: 25 }, action) { switch (action.type) { case 'UPDATE_NAME': return { ...state, name: action.payload } default: return state } } ``` ## Приклад з RTK (Immer всередині) ```javascript const userSlice = createSlice({ name: 'user', initialState: { name: 'Maria', age: 25 }, reducers: { updateName(state, action) { state.name = action.payload // працює завдяки Immer } } }) ``` Обидва роблять одне й те саме - тільки в RTK код удвічі коротший, і іммутабельність гарантована автоматично. --- ## Чому це важливо | Проблема без Immer | Що вирішує Immer | | --- | --- | | Потрібно вручну копіювати об'єкти (`{ ...state }`) | Робить це автоматично | | Помилки мутації | Виключає їх | | Складно оновлювати вкладені структури | Можна звертатися напряму (`state.user.name = ...`) | | Повільне глибоке копіювання | Копіює тільки змінені гілки | | Багато шаблонного коду | Код стає природним і коротким | --- ## Візуально (що робить Immer) ```javascript [оригінальний стан] │ ▼ створюється proxy (draft) │ ▼ ти "мутуєш" draft │ ▼ Immer фіксує зміни │ ▼ повертає новий стан (іммутабельний) ``` --- ## Підсумок | Що робить Immer всередині RTK | Як це виглядає | | --- | --- | | Створює "чернетку" стану через Proxy | `draft` | | Дозволяє мутувати `draft` | `state.value++` | | Відстежує всі зміни | через пастки Proxy | | Після виходу створює новий state | іммутабельна копія | | Копіює тільки змінені гілки | ощадливо і швидко | | Гарантує безпеку стану | без ручних spread'ів | --- **Підсумкове визначення:** > **Immer.js у Redux Toolkit** - це "невидимий посередник", > який перетворює твій "мутуючий" код на **чисту, іммутабельну трансформацію стану** > з мінімальними змінами в пам'яті і максимальною безпекою.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.