Lesson 19 / 25

persist, devtools and immer Middleware

Wrap the state creator.

Middleware wraps the creator function

Zustand middleware are functions that wrap the state creator. persist (from zustand/middleware) saves state to storage under a name key, with options such as storage: createJSONStorage(() => sessionStorage), partialize to choose fields, and version plus migrate for schema changes. devtools connects the store to the Redux DevTools extension. immer (from zustand/middleware/immer, requires the immer package) lets actions mutate a draft. When combining them, the docs recommend applying devtools last, as the outermost wrapper.

Compose, type and test

Middleware, vanilla stores and test resets make Zustand production-ready.

Three ideas: persist, devtools and immer middleware; stores outside React with TypeScript; testing.
Figure 7.1 — Middleware wrapping a store used by React and plain code.

A persisted settings store

devtools(persist(immer(...))).

import { create } from 'zustand';
import { devtools, persist, createJSONStorage } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';

type Settings = {
  theme: 'light' | 'dark';
  recent: string[];
  setTheme: (t: Settings['theme']) => void;
  remember: (q: string) => void;
};

export const useSettings = create<Settings>()(
  devtools(
    persist(
      immer((set) => ({
        theme: 'light',
        recent: [],
        setTheme: (t) => set((s) => { s.theme = t; }),
        remember: (q) => set((s) => { s.recent = [q, ...s.recent].slice(0, 5); }),
      })),
      {
        name: 'settings',
        storage: createJSONStorage(() => localStorage),
        partialize: (s) => ({ theme: s.theme, recent: s.recent }),
        version: 1,
      }
    ),
    { name: 'SettingsStore' }
  )
);

Persist only what you must

Persisted data outlives deployments. Use partialize to save only stable preferences, bump version with a migrate function when the shape changes, and never persist secrets in localStorage.

Quick check: What does the persist option partialize do?

  • Encrypts state
  • Splits the store into slices
  • Compresses state
  • Chooses which parts of state are saved to storage
Answer

Chooses which parts of state are saved to storage — Only the returned fields are persisted.