codez.guru

On this Page

  • What Is Immer and Why Use It?
  • Zustand’s immer Middleware
  • Updating Nested State
  • Tips and Warnings

On this Guide

  • Lesson 09: Organizing State with Slices and Modular Stores
  • Lesson 10: Persisting State to localStorage or sessionStorage
  • Lesson 11: Using Devtools Middleware for Debugging
  • Lesson 12: Using Zustand with Immer for Immutable Updates
  • Lesson 13: Using Zustand with Middleware: Logging, Tracking, and Side Effects
  • Lesson 14: Subscribing to External State Changes
  • Lesson 15: Creating Read-Only or Transient State Stores
  • Lesson 16: Testing Zustand Stores with React Testing Library
  • Lesson 17: Using Zustand in Server-Side Rendering (Next.js)

What Is Immer and Why Use It?

Immer allows you to write mutative code that produces immutable updates under the hood.

state.user.name = "Ziv"; // This is actually immutable with Immer!

This helps especially when:

  • Your state is deeply nested
  • You want cleaner updates
  • You want Redux-like immutability with minimal effort

Zustand’s immer Middleware

Zustand has built-in support for Immer via middleware:

import { create } from "zustand";
import { immer } from "zustand/middleware/immer";

type Todo = { id: number; title: string; done: boolean };

type TodoStore = {
  todos: Todo[];
  toggleTodo: (id: number) => void;
};

export const useTodoStore = create<todostore>()(
  immer((set) =&gt; ({
    todos: [],
    toggleTodo: (id) =&gt;
      set((state) =&gt; {
        const todo = state.todos.find((t) =&gt; t.id === id);
        if (todo) todo.done = !todo.done;
      }),
  }))
);

> ✅ state.todos is not mutated — Immer tracks changes and returns a new immutable object.


Updating Nested State

With Immer, this:

set((state) =&gt; {
  state.user.profile.avatar = "new.png";
});

is equivalent to a fully immutable deep copy update.

✅ Clean
✅ Safe
✅ Great for forms, trees, and configs


Tips and Warnings

  • immer() must wrap your store definition
  • All mutations must happen inside the set() function
  • You can use Immer with persist and devtools (wrap them carefully)
    devtools(persist(immer(...)))

Summary

  • Zustand + Immer = clean, immutable updates with mutable syntax
  • Great for deeply nested or complex state trees
  • Middleware is built-in and easy to apply
  • Pair it with other middlewares for real power

Next: Lesson 13 – Using Zustand with Middleware: Logging, Tracking, and Side Effects