Suggest an editImprove this articleRefine the answer for “What is middleware in Zustand?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Middleware in Zustand** is a wrapper function that extends the store's behavior by adding extra logic between a state change (`set`) and its actual application. **Key point:** middleware in Zustand are plugins that "hook into" the store and add new capabilities: persistence, logging, devtools, immutability, and so on.Shown above the full answer for quick recall.Answer (EN)ImageIn **Zustand**, the term **middleware** means a **wrapper function** that **extends the behavior of the store** by adding extra logic between a state change (`set`) and its actual application. In simpler terms: > **Middleware in Zustand is plugins** that "hook into" the store and add new capabilities: persistence, logging, devtools, immutability, and so on. --- ## How it works When you create a store: ```javascript import { create } from 'zustand' const useStore = create((set) => ({ count: 0, inc: () => set((s) => ({ count: s.count + 1 })), })) ``` Zustand lets you wrap this "plain" store with a middleware function to change or extend its behavior: ```javascript import { devtools } from 'zustand/middleware' const useStore = create( devtools((set) => ({ count: 0, inc: () => set((s) => ({ count: s.count + 1 })), })) ) ``` Now Zustand connects to **Redux DevTools**, and you can track state in the browser. --- ## Popular middleware in Zustand | Middleware | Purpose | |---|---| | `devtools` | integration with Redux DevTools for debugging | | `persist` | saves state to `localStorage`, `sessionStorage`, or IndexedDB | | `immer` | lets you change state "imperatively" through a `draft` (like in Redux Toolkit) | | `subscribeWithSelector` | subscription to only the fields you need (deep selectivity) | | `combine` | helps combine several state slices into one store | | `redux` | emulates Redux-like behavior with actions and reducers | --- ## Usage examples ### 1. `persist` Persists state across page reloads: ```javascript import { create } from 'zustand' import { persist } from 'zustand/middleware' const useAuthStore = create( persist( (set) => ({ user: null, setUser: (user) => set({ user }), logout: () => set({ user: null }), }), { name: 'auth-storage' } // the key in localStorage ) ) ``` Now the data will be automatically stored in `localStorage`. --- ### 2. `devtools` Adds integration with Redux DevTools: ```javascript import { create } from 'zustand' import { devtools } from 'zustand/middleware' const useCounterStore = create( devtools((set) => ({ count: 0, inc: () => set((s) => ({ count: s.count + 1 })), })) ) ``` Now you can open DevTools and see every state change. --- ### 3. `immer` Lets you use a **mutable-style update** (through a `draft`): ```javascript import { create } from 'zustand' import { immer } from 'zustand/middleware/immer' const useTodoStore = create( immer((set) => ({ todos: [], addTodo: (text) => set((state) => { state.todos.push({ text, done: false }) }), })) ) ``` Here you can "mutate" the array directly, as if it were a plain JS object - under the hood Zustand does an immutable copy. --- ### 4. Combining middleware You can use several middleware at once - just nest them: ```javascript import { create } from 'zustand' import { devtools, persist } from 'zustand/middleware' const useStore = create( devtools( persist( (set) => ({ theme: 'light', toggleTheme: () => set((s) => ({ theme: s.theme === 'light' ? 'dark' : 'light' })), }), { name: 'theme-storage' } ) ) ) ``` --- ## How middleware is built internally Middleware is a higher-order function: ```javascript type Middleware = (createState: StateCreator) => StateCreator ``` It receives `createState` (your function that creates the store) and returns a **new** function that wraps or changes the behavior of `set`, `get`, `subscribe`. An example of a custom middleware: ```javascript const logger = (config) => (set, get, api) => config( (args) => { console.log('Before:', get()) set(args) console.log('After:', get()) }, get, api ) ``` --- ## Summary | What middleware does | Example | |---|---| | Adds new functionality to the store | `persist`, `devtools`, `immer` | | Intercepts and changes `set()` | logging, filtering | | Extends the store's API | methods like `.persist.rehydrate()` | | Can be combined | `devtools(persist(...))` |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.