# persist, devtools and immer Middleware — Redux Toolkit / Zustand

Source: https://www.skillbyai.com/en/redux-zustand/z-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.](assets/figures/redux-zustand/section-7-map.svg) — Figure 7.1 — Middleware wrapping a store used by React and plain code.

## A persisted settings store

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

```typescript
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.

**Quiz:** What does the persist option partialize do?

- [ ] Encrypts state
- [ ] Splits the store into slices
- [ ] Compresses state
- [x] 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.
