Skip to content
Skillv1.0.0

zustand-state-management

Zustand state management for React with TypeScript. Use for global state, Redux/Context API migration, localStorage persistence, slices pattern, devtools, Next.js SSR, or encountering hydration errors

by secondsky(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from secondsky/claude-skills (plugins/zustand-state-management/skills/zustand-state-management/SKILL.md). Install upstream with npx skills add secondsky/claude-skills --skill zustand-state-management. Copyright stays with the author (MIT).

Zustand State Management

Status: Production Ready ✅ Last Updated: 2026-08-03 Latest Version: zustand@5.0.14 Dependencies: React 18+, TypeScript 5+


Quick Start (3 Minutes)

1. Install Zustand

bun add zustand  # preferred
# or: npm install zustand
# or: yarn add zustand

Why Zustand?

  • Minimal API: Only 1 function to learn (create)
  • No boilerplate: No providers, reducers, or actions
  • TypeScript-first: Excellent type inference
  • Fast: Fine-grained subscriptions prevent unnecessary re-renders
  • Flexible: Middleware for persistence, devtools, and more

2. Create Your First Store (TypeScript)

import { create } from 'zustand'

interface BearStore {
  bears: number
  increase: (by: number) => void
  reset: () => void
}

const useBearStore = create<BearStore>()((set) => ({
  bears: 0,
  increase: (by) => set((state) => ({ bears: state.bears + by })),
  reset: () => set({ bears: 0 }),
}))

CRITICAL: Notice the double parentheses create<T>()() - this is required for TypeScript with middleware.

3. Use Store in Components

import { useBearStore } from './store'

function BearCounter() {
  const bears = useBearStore((state) => state.bears)
  return <h1>{bears} around here...</h1>
}

function Controls() {
  const increase = useBearStore((state) => state.increase)
  return <button onClick={() => increase(1)}>Add bear</button>
}

Why this works:

  • Components only re-render when their selected state changes
  • No Context providers needed
  • Selector function extracts specific state slice

The 3-Pattern Setup Process

Pattern 1: Basic Store (JavaScript)

For simple use cases without TypeScript:

import { create } from 'zustand'

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}))

When to use:

  • Prototyping
  • Small apps
  • No TypeScript in project

Pattern 2: TypeScript Store (Recommended)

For production apps with type safety:

import { create } from 'zustand'

// Define store interface
interface CounterStore {
  count: number
  increment: () => void
  decrement: () => void
}

// Create typed store
const useCounterStore = create<CounterStore>()((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}))

Key Points:

  • Separate interface for state + actions
  • Use create<T>()() syntax (currying for middleware)
  • Full IDE autocomplete and type checking

Pattern 3: Persistent Store

For state that survives page reloads:

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

interface UserPreferences {
  theme: 'light' | 'dark' | 'system'
  language: string
  setTheme: (theme: UserPreferences['theme']) => void
  setLanguage: (language: string) => void
}

const usePreferencesStore = create<UserPreferences>()(
  persist(
    (set) => ({
      theme: 'system',
      language: 'en',
      setTheme: (theme) => set({ theme }),
      setLanguage: (language) => set({ language }),
    }),
    {
      name: 'user-preferences', // unique name in localStorage
      storage: createJSONStorage(() => localStorage), // optional: defaults to localStorage
    },
  ),
)

Why this matters:

  • State automatically saved to localStorage
  • Restored on page reload
  • Works with sessionStorage too
  • Handles serialization automatically

Critical Rules

Always Do

✅ Use create<T>()() (double parentheses) in TypeScript for middleware compatibility ✅ Define separate interfaces for state and actions ✅ Use selector functions to extract specific state slices ✅ Use set with updater functions for derived state: set((state) => ({ count: state.count + 1 })) ✅ Use unique names for persist middleware storage keys ✅ Handle Next.js hydration with hasHydrated flag pattern ✅ Use shallow for selecting multiple values ✅ Keep actions pure (no side effects except state updates)

Never Do

❌ Use create<T>(...) (single parentheses) in TypeScript - breaks middleware types ❌ Mutate state directly: set((state) => { state.count++; return state }) - use immutable updates ❌ Create new objects in selectors: useStore((state) => ({ a: state.a })) - causes infinite renders ❌ Use same storage name for multiple stores - causes data collisions ❌ Access localStorage during SSR without hydration check ❌ Use Zustand for server state - use TanStack Query instead ❌ Export store instance directly - always export the hook


Known Issues Prevention (5 Issues)

Issue Error Quick Fix
#1 Hydration mismatch "Text content does not match" Use _hasHydrated flag + onRehydrateStorage
#2 TypeScript inference Types break with middleware Use create<T>()() double parentheses
#3 Import error "createJSONStorage not exported" Upgrade to zustand@5.0.14+
#4 Infinite loop Browser freezes Use shallow or separate selectors
#5 Slices types StateCreator types fail Explicit StateCreator<Combined, [], [], Slice>

Most Critical - TypeScript double parentheses:

// ❌ WRONG: create<T>((set) => ...)
// ✅ CORRECT: create<T>()((set) => ...)

See: references/known-issues.md for complete solutions with code examples.


Middleware Configuration

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

const useStore = create<MyStore>()(
  devtools(
    persist(
      (set) => ({ /* store definition */ }),
      { name: 'my-storage' },
    ),
    { name: 'MyStore' },
  ),
)
Middleware Purpose Import
persist localStorage/sessionStorage zustand/middleware
devtools Redux DevTools integration zustand/middleware
immer Mutable update syntax zustand/middleware/immer

Order matters: devtools(persist(...)) shows persist actions in DevTools.

See: references/middleware-guide.md for complete middleware documentation.


Common Patterns

Pattern Use Case Key Technique
Computed values Derived data Compute in selector: state.items.length
Async actions API calls set({ isLoading: true }) + try/catch
Reset store Logout, form clear set(initialState)
Selector with params Dynamic access state.todos.find(t => t.id === id)
Multiple stores Separation of concerns Create separate create() calls

See: references/common-patterns.md for complete implementations.


Advanced Topics

Topic Use Case Key API
Vanilla store Non-React, testing createStore() from zustand/vanilla
Custom middleware Logging, timestamps Wrap StateCreator
Immer Mutable update syntax immer() middleware
Subscriptions Side effects store.subscribe()

See: references/advanced-topics.md for complete implementations.


Bundled Resources

Type Files
Templates basic-store.ts, typescript-store.ts, persist-store.ts, slices-pattern.ts, devtools-store.ts, nextjs-store.ts, computed-store.ts, async-actions-store.ts
References middleware-guide.md, typescript-patterns.md, nextjs-hydration.md, migration-guide.md, known-issues.md, common-patterns.md, advanced-topics.md

When to Load References

Reference Load When...
known-issues.md Debugging hydration, TypeScript, infinite loop, or slices errors
common-patterns.md Implementing computed values, async actions, reset patterns
advanced-topics.md Vanilla stores, custom middleware, Immer, subscriptions
middleware-guide.md Configuring persist, devtools, or combining middlewares
typescript-patterns.md Complex type inference issues, StateCreator problems
nextjs-hydration.md Next.js SSR/hydration problems
migration-guide.md Migrating from Redux, Context API, or Zustand v4

Quick Troubleshooting

Problem Solution
Store updates don't trigger re-renders Use selector: useStore(state => state.value) not destructuring
TypeScript errors with middleware Use create<T>()() double parentheses
Hydration error with persist Implement _hasHydrated flag pattern
Actions not showing in DevTools Pass action name: set(newState, undefined, 'actionName')
Store resets unexpectedly HMR causes reset in development

Dependencies

{ "dependencies": { "zustand": "^5.0.14", "react": "^18.0.0+" } }

Compatibility: React 18+, React 19, TypeScript 5+, Next.js 14+, Vite 5+


Official Docs: https://zustand.docs.pmnd.rs/ | GitHub: https://github.com/pmndrs/zustand

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/secondsky-claude-skills-zustand-state-management/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

secondsky-claude-skills-zustand-state-management.ocm.jsonjson
{
  "ocm": "1",
  "id": "secondsky-claude-skills-zustand-state-management",
  "kind": "skill",
  "name": "zustand-state-management",
  "description": "Zustand state management for React with TypeScript. Use for global state, Redux/Context API migration, localStorage persistence, slices pattern, devtools, Next.js SSR, or encountering hydration errors, TypeScript inference issues, persist middleware problems, infinite render loops.",
  "publisher": "secondsky",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "zustand",
      "state-management",
      "react-state",
      "typescript-state",
      "persist-middleware",
      "devtools",
      "slices-pattern",
      "global-state",
      "react-hooks"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Zustand state management for React with TypeScript. Use for global state, Redux/Context API migration, localStorage persistence, slices pattern, devtools, Next.js SSR, or encountering hydration errors, TypeScript inference issues, persist middleware problems, infinite render loops."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/secondsky/claude-skills",
      "path": "plugins/zustand-state-management/skills/zustand-state-management/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/secondsky/claude-skills/blob/HEAD/plugins/zustand-state-management/skills/zustand-state-management/SKILL.md",
      "key": "secondsky/claude-skills/plugins/zustand-state-management/skills/zustand-state-management/SKILL.md"
    },
    "license": "MIT"
  },
  "instructions": "# Zustand State Management\n\n**Status**: Production Ready ✅\n**Last Updated**: 2026-08-03\n**Latest Version**: zustand@5.0.14\n**Dependencies**: React 18+, TypeScript 5+\n\n---\n\n## Quick Start (3 Minutes)\n\n### 1. Install Zustand\n\n```bash\nbun add zustand  # preferred\n# or: npm install zustand\n# or: yarn add zustand\n```\n\n**Why Zustand?**\n- Minimal API: Only 1 function to learn (`create`)\n- No boilerplate: No providers, reducers, or actions\n- TypeScript-first: Excellent type inference\n- Fast: Fine-grained subscriptions prevent unnecessary re-renders\n- Flexible: Middleware for persistence, devtools, and",
  "cost": {
    "context_tokens": 2282
  }
}

Fetch it by URL: GET /api/v1/registry/secondsky-claude-skills-zustand-state-management/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.