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, TypeScript inference issues, persist middleware problems, infinite render loops.
What this skill does
# Zustand State Management **Status**: Production Ready ✅ **Last Updated**: 2025-11-21 **Latest Version**: [email protected] **Dependencies**: React 18+, TypeScript 5+ --- ## Quick Start (3 Minutes) ### 1. Install Zustand ```bash 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) ```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 ```tsx 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: ```javascript 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: ```typescript 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: ```typescript 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 [email protected]+ | | **#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: ```typescript // ❌ WRONG: create<T>((set) => ...) // ✅ CORRECT: create<T>()((set) => ...) ``` **See**: `references/known-issues.md` for complete solutions with code examples. --- ## Middleware Configuration ```typescript 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,
Related in Image & Video
watch
IncludedWatch a video (URL or local path). Downloads with yt-dlp, extracts auto-scaled frames with ffmpeg, pulls the transcript from captions (or Whisper API fallback), and hands the result to Claude so it can answer questions about what's in the video.
physical-ai-defect-image-generation
IncludedUse when the user wants to orchestrate defect image generation, run associated setup, or handle outputs on OSMO. The Day 0 path handles cold-start with USD-to-ROI, image-edit augmentation, and AnomalyGen to create initial PCBA datasets. The Day 1 path performs inference and labeling on real images. This skill helps with first-time asset setup, creation of finetuning checkpoints, and configuring deployment. Trigger keywords: defect image generation, dig workflow, dig pipeline, defect image detection workflow, aoi pipeline, aoi anomalygen, usd2roi anomalygen, day 0 pcba, day 1 pcba, day 1 real-photo alignment, day 1 manual roi, metal surface anomaly, glass defect, anomalygen finetune, setup_pcb, setup_metal, setup_glass, setup_pretrained, dig setup, dig datasets, dig pretrained checkpoint, dig image-edit endpoint.
accelint-react-best-practices
IncludedReact performance optimization and best practices. ALWAYS use this skill when working with any React code - writing components, hooks, JSX; refactoring; optimizing re-renders, memoization, state management; reviewing for performance; fixing hydration mismatches; debugging infinite re-renders, stale closures, input focus loss, animations restarting; preventing remounting; implementing transitions, lazy initialization, effect dependencies. Even simple React tasks benefit from these patterns. Covers React 19+ (useEffectEvent, Activity, ref props). Triggers - useEffect, useState, useMemo, useCallback, memo, inline components, nested components, components inside components, re-render, performance, hydration, SSR, Next.js, useDeferredValue, combined hooks.
elevenlabs-agents
IncludedBuild conversational AI voice agents with ElevenLabs Platform using React, JavaScript, React Native, or Swift SDKs. Configure agents, tools (client/server/MCP), RAG knowledge bases, multi-voice, and Scribe real-time STT. Use when: building voice chat interfaces, implementing AI phone agents with Twilio, configuring agent workflows or tools, adding RAG knowledge bases, testing with CLI "agents as code", or troubleshooting deprecated @11labs packages, Android audio cutoff, CSP violations, dynamic variables, or WebRTC config. Keywords: ElevenLabs Agents, ElevenLabs voice agents, AI voice agents, conversational AI, @elevenlabs/react, @elevenlabs/client, @elevenlabs/react-native, @elevenlabs/elevenlabs-js, @elevenlabs/agents-cli, elevenlabs SDK, voice AI, TTS, text-to-speech, ASR, speech recognition, turn-taking model, WebRTC voice, WebSocket voice, ElevenLabs conversation, agent system prompt, agent tools, agent knowledge base, RAG voice agents, multi-voice agents, pronunciation dictionary, voice speed control, elevenlabs scribe, @11labs deprecated, Android audio cutoff, CSP violation elevenlabs, dynamic variables elevenlabs, case-sensitive tool names, webhook authentication
humanizer
IncludedHumanize AI-generated text by detecting and removing patterns typical of LLM output. Rewrites text to sound natural, specific, and human. Uses 28 pattern detectors, 560+ AI vocabulary terms across 3 tiers, and statistical analysis (burstiness, type-token ratio, readability) for comprehensive detection. Use when asked to humanize text, de-AI writing, make content sound more natural/human, review writing for AI patterns, score text for AI detection, or improve AI-generated drafts. Covers content, language, style, communication, and filler categories.
generating-mermaid-diagrams
IncludedSalesforce architecture diagrams using Mermaid with ASCII fallback. Use this skill when generating text-based diagrams for Salesforce architecture, OAuth flows, ERDs, integration sequences, or Agentforce structure. TRIGGER when: user says "diagram", "visualize", "ERD", or asks for sequence diagrams, flowcharts, class diagrams, or architecture visualizations in Mermaid. DO NOT TRIGGER when: user wants PNG/SVG image output (use generating-visual-diagrams), or asks about non-Salesforce systems.