zustand

Zustand v5 is a lightweight global state manager for React built on useSyncExternalStore.

oakoss/agent-skills106 installsMITSynced Aug 26

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI

Agent Skills format with YAML frontmatter. Claude Code reads it as-is.

---
name: "zustand"
description: "Zustand v5 is a lightweight global state manager for React built on useSyncExternalStore."
license: "MIT"
---

# Zustand State Management

## Overview

Zustand v5 is a lightweight global state manager for React built on `useSyncExternalStore`. Requires React 18+ (uses `useSyncExternalStore` internally). When using `createWithEqualityFn`, install `use-sync-external-store` as a peer dependency. It provides type-safe stores, atomic selectors for minimal re-renders, composable middleware (persist, devtools, immer, subscribeWithSelector), and a slices pattern for large applications. Use Zustand for client-only global state; use TanStack Query for server-fetched data.

**When to use:** Client-side global state, persistent user preferences, complex multi-domain stores, cross-component state sharing, vanilla (non-React) state management.

**When NOT to use:** Server state with caching needs (use TanStack Query), single-component state (use useState), simple prop drilling scenarios.

## Quick Reference

| Pattern               | API                                     | Key Points                                       |
| --------------------- | --------------------------------------- | ------------------------------------------------ |
| Basic store           | `create<T>()((set) => ({...}))`         | Double parentheses required for TS               |
| Atomic selector       | `useStore(state => state.bears)`        | Only re-renders when selected value changes      |
| Multiple values       | `useShallow(state => ({a, b}))`         | Import from `zustand/react/shallow`              |
| Persist               | `persist(fn, { name })`                 | localStorage with SSR hydration handling         |
| Devtools              | `devtools(fn, { name })`                | Redux DevTools integration                       |
| SubscribeWithSelector | `subscribeWithSelector(fn)`             | Subscribe to state slices outside React          |
| Middleware order      | `devtools(persist(fn))`                 | Outer to inner wrapping                          |
| Slices pattern        | `StateCreator<Combined, [], [], Slice>` | Split store by domain                            |
| SSR provider          | `createStore` + React Context           | Per-request stores prevent data leaks            |
| Immer                 | `immer(fn)`                             | Safe nested state mutations                      |
| Vanilla store         | `createStore` from `zustand/vanilla`    | Use outside React                                |
| Reset store           | `set(store.getInitialState())`          | Use `getInitialState()` for reliable reset       |
| Derived values        | `useStore(s => s.items.length)`         | Compute in selector                              |
| Auto selectors        | `createSelectors(store)`                | Generate `store.use.field()` hooks automatically |

## Common Mistakes

| Mistake                                                                   | Correct Pattern                                                                                   |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| Using `create<T>(...)` with single parentheses                            | Use `create<T>()(...)` double parentheses for correct TypeScript middleware inference             |
| Selecting full state object with `useStore(state => state)`               | Use atomic selectors like `state.bears` or `useShallow` to avoid unnecessary re-renders           |
| Importing `useShallow` from `zustand/shallow`                             | Import from `zustand/react/shallow`; `zustand/shallow` exports the plain `shallow` function only  |
| Creating new object references in selectors causing infinite loops        | Use separate primitive selectors or wrap with `useShallow` from `zustand/react/shallow`           |
| Using a global singleton store with SSR or Next.js                        | Use the `StoreContext` provider pattern with `createStore` to prevent data leaks between requests |
| Tracking initial state manually for reset                                 | Use `store.getInitialState()` which Zustand provides automatically                                |
| Using Zustand for server-fetched data that needs caching and revalidation | Use TanStack Query for server state; reserve Zustand for client-only global state                 |

## Delegation

- **Store architecture and slices design**: Use `Plan` agent to define domain boundaries, slice interfaces, and middleware composition order
- **Hydration and SSR debugging**: Use `Task` agent to diagnose persist middleware issues, hydration mismatches, and Next.js provider setup
- **Migration from v4 to v5**: Use `Explore` agent to find deprecated import paths, single-parentheses patterns, and legacy middleware usage
- **Testing strategy**: Use `Task` agent to set up store mocks and test isolation patterns

## References

- [Store patterns, TypeScript, and core API](references/store-patterns.md)
- [Middleware: persist, devtools, immer, subscribeWithSelector, and custom](references/middleware.md)
- [Slices pattern and large store architecture](references/slices-pattern.md)
- [SSR, Next.js, and hydration handling](references/ssr-hydration.md)
- [Testing stores with Vitest and Jest](references/testing.md)
- [Migration guide: Redux, Context, and v4 to v5](references/migration.md)

More General & Other skills

← All General & Other skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY