Що робить Immer.js всередині Redux Toolkit?
Коротка відповідь
Immer.js всередині Redux Toolkit відповідає за іммутабельне оновлення стану. Він дозволяє тобі писати код так, ніби ти мутуєш об'єкт, але насправді створює новий, незмінний стан за допомогою Proxy.
Що відбувається при виклику createSlice()
Коли ти пишеш редьюсер у RTK на кшталт цього:
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment(state) {
state.value++ // ← ти ніби мутуєш
},
},
})RTK не зберігає цей reducer напряму. Під капотом він огортає твою функцію через Immer:
import { produce } from 'immer'
function wrappedReducer(state, action) {
return produce(state, draft => {
state.value++ // ← стає "draft.value++"
})
}Immer бере state, створює для нього "чернетку" (draft),
дозволяє в ній робити зміни, і після завершення повертає новий стан,
у якому змінені лише потрібні поля, а все решта - те саме (за посиланнями).
Як працює produce() (серце Immer)
Ось мінімальна реалізація "магії":
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 під капотом
- Створює Proxy для об'єкта
stateКожен доступ до властивості (get,set,delete) перехоплюється. - Запам'ятовує всі зміни, які ти зробив Immer не змінює об'єкт одразу - він записує інструкції:
- збільшити count
- змінити user.name- Після виходу з
produce()Immer створює нове дерево стану, копіюючи лише змінені частини. Усе, що не змінювалося, залишається за старими посиланнями → це дуже ефективно за пам'яттю. - Повертає новий state Новий об'єкт "чистий" і іммутабельний - його можна безпечно передавати далі в Redux.
Приклад: вкладені зміни
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().
Кожен редьюсер, який ти оголошуєш, фактично стає:
(state, action) => produce(state, draft => {
// твій код
})У RTK це робиться автоматично, тобі не потрібно явно викликати produce().
Приклад без RTK (чистий Redux)
function userReducer(state = { name: 'Maria', age: 25 }, action) {
switch (action.type) {
case 'UPDATE_NAME':
return { ...state, name: action.payload }
default:
return state
}
}Приклад з RTK (Immer всередині)
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)
[оригінальний стан]
│
▼
створюється proxy (draft)
│
▼
ти "мутуєш" draft
│
▼
Immer фіксує зміни
│
▼
повертає новий стан (іммутабельний)Підсумок
| Що робить Immer всередині RTK | Як це виглядає |
|---|---|
| Створює "чернетку" стану через Proxy | draft |
Дозволяє мутувати draft | state.value++ |
| Відстежує всі зміни | через пастки Proxy |
| Після виходу створює новий state | іммутабельна копія |
| Копіює тільки змінені гілки | ощадливо і швидко |
| Гарантує безпеку стану | без ручних spread'ів |
Підсумкове визначення:
Immer.js у Redux Toolkit - це "невидимий посередник", який перетворює твій "мутуючий" код на чисту, іммутабельну трансформацію стану з мінімальними змінами в пам'яті і максимальною безпекою.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.