On this Page
- What Is Immer and Why Use It?
- Zustand’s
immerMiddleware - 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) => ({
todos: [],
toggleTodo: (id) =>
set((state) => {
const todo = state.todos.find((t) => 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) => {
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
persistanddevtools(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