Zustand Middleware: Intercept Every Set Call
Zustand middleware intercepts set calls to add logging, persistence, or devtools without touching business logic. Use it when updates need the same side effect, like localStorage sync.
WHY IT EXISTS: Zustand keeps its core tiny by design, but real applications need side effects that span many updates. Without middleware, you would scatter localStorage calls, logger statements, and devtool hooks across every action creator or component. Middleware was introduced to centralize these cross-cutting concerns into a single composable layer that sits between your store and the outside world.
THE MENTAL MODEL: Think of it as an assembly line inspector for state updates. Every time your code calls set, the update first rolls through a series of middleware stations where it can be logged, transformed, persisted, or broadcast. Only after passing through the chain does the new state reach your React components. This keeps your store functions focused on business rules while the pipeline handles plumbing.
HOW IT WORKS: A middleware is a higher-order function that receives set, get, and the store api, then returns a wrapped version of set. For example, a logger middleware might capture the previous state, invoke the original set with the next state, then print both to the console. A persistence middleware can intercept the set call, allow the update to proceed, and then write the result to localStorage. Because middleware composes by wrapping, order matters: the first middleware in the chain sees the raw update, while the last sees the fully processed state.
WHEN TO USE IT: Three signals you should use middleware. First, you need Redux DevTools integration to time-travel debug outside of production. Second, you want state to survive page refreshes by syncing to local or session storage. Third, you must emit analytics or telemetry on every user action without cluttering individual setters. If the behavior applies to every update uniformly, middleware is the right home.
WHEN NOT TO USE IT: Do not use middleware for logic that belongs inside a specific slice or React component. Because middleware runs on every set call, placing expensive computation or conditional business rules here creates a hidden tax on every interaction. Another footgun is mutating the draft state inside middleware instead of passing it through cleanly, which can corrupt the update flow and break React reactivity.
ONE CANONICAL EXAMPLE: A logger middleware starts as a function that accepts a store configuration and returns another function receiving set, get, and api. Inside, it returns a new set function that first applies the original set, then reads get to capture the updated state, and finally prints a formatted log to the console. When you attach this middleware during store creation, every set call automatically produces a trace without a single line of logging inside your components or action functions.
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.