Skip to main content

What does Immer.js do inside Redux Toolkit?

Short answer

Immer.js inside Redux Toolkit is responsible for immutable state updates. It lets you write code as if you were mutating an object, but it actually creates a new, unchanged state using a Proxy.


What happens when you call createSlice()

When you write a reducer in RTK like this:

javascript
const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment(state) { state.value++ // ← you seem to be mutating }, }, })

RTK does not store this reducer directly. Under the hood it wraps your function with Immer:

javascript
import { produce } from 'immer' function wrappedReducer(state, action) { return produce(state, draft => { state.value++ // ← becomes "draft.value++" }) }

Immer takes state, creates a "draft" of it, lets you make changes to it, and once finished returns a new state, in which only the needed fields are changed, while everything else stays the same (by reference).


How produce() works (the heart of Immer)

Here is a minimal implementation of the "magic":

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' } } unchanged

What Immer actually does under the hood

  1. Creates a Proxy for the state object Every property access (get, set, delete) is intercepted.
  2. Remembers every change you make Immer does not change the object right away - it records instructions:
javascript
- increment count - change user.name
  1. After exiting produce() Immer creates a new state tree, copying only the changed parts. Everything that was not changed stays at the old references → this is very memory-efficient.
  2. Returns the new state The new object is "clean" and immutable - it can safely be passed on into Redux.

Example: nested changes

javascript
const state = { user: { name: 'Maria', age: 25 }, settings: { theme: 'dark' } } const next = produce(state, draft => { draft.user.age = 26 })

Immer:

  • Creates a new copy of only the user branch
  • settings stays at the same reference
  • So next.settings === state.settingstrue

This makes updates very performant, because only the changed part of the tree gets copied.


How RTK uses Immer internally

Redux Toolkit integrates Immer into createReducer() and createSlice().

Every reducer you declare effectively becomes:

javascript
(state, action) => produce(state, draft => { // your code })

In RTK this happens automatically, so you do not need to call produce() explicitly.


Example without RTK (plain Redux)

javascript
function userReducer(state = { name: 'Maria', age: 25 }, action) { switch (action.type) { case 'UPDATE_NAME': return { ...state, name: action.payload } default: return state } }

Example with RTK (Immer inside)

javascript
const userSlice = createSlice({ name: 'user', initialState: { name: 'Maria', age: 25 }, reducers: { updateName(state, action) { state.name = action.payload // works thanks to Immer } } })

Both do the same thing - only in RTK the code is twice as short, and immutability is guaranteed automatically.


Why this matters

Problem without ImmerWhat Immer solves
You have to copy objects manually ({ ...state })Does it automatically
Mutation bugsEliminates them
Hard to update nested structuresYou can access it directly (state.user.name = ...)
Slow deep copyingCopies only the changed branches
A lot of boilerplateThe code becomes natural and short

Visually (what Immer does)

javascript
[original state] a proxy (draft) is created you "mutate" the draft Immer records the changes returns the new state (immutable)

Summary

What Immer does inside RTKWhat it looks like
Creates a state "draft" via a Proxydraft
Lets you mutate the draftstate.value++
Tracks all changesthrough Proxy traps
Creates a new state on exitan immutable copy
Copies only the changed branchesefficient and fast
Guarantees state safetywithout manual spreads

Summary definition:

Immer.js in Redux Toolkit is an "invisible intermediary" that turns your "mutating" code into a clean, immutable state transformation with minimal memory changes and maximum safety.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.