# Zustand Middleware Complete Guide Complete reference for all Zustand middleware. Load when user asks about persistence, devtools, immer, or custom middleware. --- ## Persist Middleware ### Basic Usage ```typescript import { create } from 'zustand' import { persist, createJSONStorage } from 'zustand/middleware' const useStore = create()( persist( (set) => ({ /* store */ }), { name: 'storage-name' } ) ) ``` ### Storage Options ```typescript // localStorage (default) storage: createJSONStorage(() => localStorage) // sessionStorage storage: createJSONStorage(() => sessionStorage) // Custom storage storage: createJSONStorage(() => customStorage) ``` ### Partial Persistence ```typescript persist( (set) => ({ /* store */ }), { name: 'storage', partialize: (state) => ({ theme: state.theme, // Don't persist sensitive data }), } ) ``` ### Schema Migration ```typescript persist( (set) => ({ /* store */ }), { name: 'storage', version: 2, migrate: (persistedState: any, version) => { if (version === 0) { // v0 → v1 persistedState.newField = 'default' } if (version === 1) { // v1 → v2 delete persistedState.oldField } return persistedState }, } ) ``` --- ## Devtools Middleware ### Basic Usage ```typescript import { devtools } from 'zustand/middleware' const useStore = create()( devtools( (set) => ({ /* store */ }), { name: 'StoreName' } ) ) ``` ### Named Actions ```typescript increment: () => set( (state) => ({ count: state.count + 1 }), undefined, 'counter/increment' // Shows in DevTools ) ``` ### Production Toggle ```typescript devtools( (set) => ({ /* store */ }), { name: 'Store', enabled: process.env.NODE_ENV === 'development' } ) ``` --- ## Immer Middleware Allows mutable state updates (Immer handles immutability): ```typescript import { immer } from 'zustand/middleware/immer' const useStore = create()( immer((set) => ({ todos: [], addTodo: (text) => set((state) => { // Mutate directly! state.todos.push({ id: Date.now(), text }) }), })) ) ``` **When to use**: Complex nested state updates --- ## Combining Middlewares ### Order Matters ```typescript // ✅ CORRECT: devtools wraps persist const useStore = create()( devtools( persist( (set) => ({ /* store */ }), { name: 'storage' } ), { name: 'Store' } ) ) // Shows persist actions in DevTools ``` ### Common Combinations ```typescript // Persist + Devtools devtools(persist(...), { name: 'Store' }) // Persist + Immer persist(immer(...), { name: 'storage' }) // All three devtools( persist( immer(...), { name: 'storage' } ), { name: 'Store' } ) ``` --- ## Custom Middleware ### Logger Example ```typescript const logger = (config) => (set, get, api) => { return config( (...args) => { console.log('Before:', get()) set(...args) console.log('After:', get()) }, get, api ) } const useStore = create(logger((set) => ({ /* store */ }))) ``` ### TypeScript Logger ```typescript import { StateCreator } from 'zustand' type Logger = ( f: StateCreator, name?: string ) => StateCreator const logger: Logger = (f, name) => (set, get, store) => { const loggedSet: typeof set = (...a) => { set(...(a as Parameters)) console.log(`[${name}]:`, get()) } return f(loggedSet, get, store) } ``` --- ## Middleware API Reference ### persist() ```typescript persist( stateCreator: StateCreator, options: { name: string // Storage key (required) storage?: PersistStorage // Storage engine partialize?: (state: T) => Partial // Select what to persist version?: number // Schema version migrate?: (state: any, version: number) => T // Migration function merge?: (persisted: any, current: T) => T // Custom merge onRehydrateStorage?: (state: T) => void // Hydration callback } ) ``` ### devtools() ```typescript devtools( stateCreator: StateCreator, options?: { name?: string // Store name in DevTools enabled?: boolean // Enable/disable } ) ``` ### immer() ```typescript immer( stateCreator: StateCreator ) ``` --- ## Common Patterns ### Reset Store ```typescript const initialState = { count: 0 } const useStore = create()( persist( (set) => ({ ...initialState, reset: () => set(initialState), }), { name: 'storage' } ) ) ``` ### Clear Persisted Data ```typescript // Clear localStorage localStorage.removeItem('storage-name') // Or programmatically const useStore = create()( persist( (set) => ({ clearStorage: () => { localStorage.removeItem('storage-name') set(initialState) }, }), { name: 'storage-name' } ) ) ``` --- ## Official Documentation - **Persist**: https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md - **Devtools**: https://github.com/pmndrs/zustand/blob/main/docs/middlewares/devtools.md - **Immer**: https://github.com/pmndrs/zustand/blob/main/docs/middlewares/immer.md