nextjs-zustand
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseZustand for Next.js 16
在 Next.js 16 中使用 Zustand
Minimal, scalable state management with React 18+ useSyncExternalStore.
基于React 18+ useSyncExternalStore的轻量级、可扩展状态管理方案。
Agent Workflow (MANDATORY)
Agent 工作流(强制要求)
Before ANY implementation, use to spawn 3 agents:
TeamCreate- fuse-ai-pilot:explore-codebase - Analyze existing stores and state patterns
- fuse-ai-pilot:research-expert - Verify latest Zustand v5 docs via Context7/Exa
- mcp__context7__query-docs - Check middleware and TypeScript patterns
After implementation, run fuse-ai-pilot:sniper for validation.
在进行任何实现之前,使用生成3个Agent:
TeamCreate- fuse-ai-pilot:explore-codebase - 分析现有状态存储和状态模式
- fuse-ai-pilot:research-expert - 通过Context7/Exa验证最新的Zustand v5文档
- mcp__context7__query-docs - 检查中间件和TypeScript模式
实现完成后,运行fuse-ai-pilot:sniper进行验证。
Overview
概述
When to Use
使用场景
- Managing client-side state in Next.js App Router applications
- Need global state across Client Components only
- Persisting state to localStorage/sessionStorage
- Building UI state (modals, sidebars, theme, cart)
- Replacing React Context for complex state
- 在Next.js App Router应用中管理客户端状态
- 仅需要在Client Components之间共享全局状态
- 将状态持久化到localStorage/sessionStorage
- 构建UI状态(模态框、侧边栏、主题、购物车)
- 替代React Context处理复杂状态
Why Zustand v5
选择Zustand v5的原因
| Feature | Benefit |
|---|---|
| Minimal API | Simple create() function, no boilerplate |
| React 18 native | useSyncExternalStore, no shims needed |
| TypeScript first | Full inference with currying pattern |
| Middleware stack | devtools, persist, immer composable |
| Bundle size | ~2KB gzipped, smallest state library |
| No providers | Direct store access, no Context wrapper |
| 特性 | 优势 |
|---|---|
| 极简API | 简单的create()函数,无需冗余代码 |
| 原生支持React 18 | 基于useSyncExternalStore,无需垫片 |
| 优先支持TypeScript | 通过柯里化模式实现完整类型推断 |
| 中间件栈 | devtools、persist、immer可组合使用 |
| 包体积 | 压缩后约2KB,体积最小的状态管理库之一 |
| 无需Provider | 直接访问状态存储,无需Context包装器 |
Critical Rules
核心规则
- Client Components ONLY - Never use Zustand in Server Components
- Context pattern for App Router - Avoid global stores (request isolation)
- useShallow for arrays/objects - Prevent unnecessary re-renders
- skipHydration with persist - Required for SSR compatibility
- Currying syntax v5 -
create<State>()((set) => ({...})) - SOLID paths - Stores in
modules/[feature]/src/stores/
- 仅用于Client Components - 绝不要在Server Components中使用Zustand
- App Router的Context模式 - 避免全局状态存储(请求隔离)
- 对数组/对象使用useShallow - 防止不必要的重渲染
- 持久化时使用skipHydration - SSR兼容性的必要配置
- v5柯里化语法 -
create<State>()((set) => ({...})) - SOLID路径 - 状态存储放在目录下
modules/[feature]/src/stores/
SOLID Architecture
SOLID 架构
Module Structure
模块结构
Stores organized by feature module:
- - Shared stores (theme, ui)
modules/cores/stores/ - - Auth state
modules/auth/src/stores/ - - Cart state
modules/cart/src/stores/ - - Store types
modules/[feature]/src/interfaces/
按功能模块组织状态存储:
- - 共享状态存储(主题、UI)
modules/cores/stores/ - - 认证状态
modules/auth/src/stores/ - - 购物车状态
modules/cart/src/stores/ - - 状态存储类型定义
modules/[feature]/src/interfaces/
File Organization
文件组织结构
| File | Purpose | Max Lines |
|---|---|---|
| Store creation with create() | 50 |
| TypeScript interfaces | 30 |
| Context provider (App Router) | 40 |
| Custom hook with selector | 20 |
| 文件 | 用途 | 最大行数 |
|---|---|---|
| 使用create()创建状态存储 | 50 |
| TypeScript接口定义 | 30 |
| Context提供者(App Router) | 40 |
| 带选择器的自定义Hook | 20 |
Key Concepts
核心概念
Store Creation (v5 Syntax)
状态存储创建(v5语法)
Double parentheses required for TypeScript inference. Currying pattern ensures full type safety.
需要双括号以实现TypeScript类型推断。柯里化模式确保完整的类型安全。
Context-Based Stores
基于Context的状态存储
For Next.js App Router, wrap stores in Context to prevent request-sharing. Use from with for initialization.
createStorezustand/vanillauseRef对于Next.js App Router,将状态存储包装在Context中以避免请求共享。使用中的结合进行初始化。
zustand/vanillacreateStoreuseRefMiddleware Composition
中间件组合
Stack middlewares: devtools → persist → immer. Order matters for TypeScript types.
堆叠中间件:devtools → persist → immer。顺序对TypeScript类型有影响。
Hydration Handling
水合处理
Use with persist middleware. Manually rehydrate in useEffect to avoid SSR mismatches.
skipHydration: true在persist中间件中使用。在useEffect中手动执行水合以避免SSR不匹配问题。
skipHydration: trueReference Guide
参考指南
| Need | Reference |
|---|---|
| Initial setup | installation.md |
| Store patterns | store-patterns.md |
| SSR/Hydration | hydration.md |
| Middleware | middleware.md |
| Next.js App Router | nextjs-integration.md |
| TypeScript | typescript.md |
| Slices pattern | slices.md |
| Auto selectors | auto-selectors.md |
| Reset state | reset-state.md |
| Subscribe API | subscribe-api.md |
| Testing | testing.md |
| Migration v4→v5 | migration-v5.md |
| 需求 | 参考文档 |
|---|---|
| 初始设置 | installation.md |
| 状态存储模式 | store-patterns.md |
| SSR/水合 | hydration.md |
| 中间件 | middleware.md |
| Next.js App Router集成 | nextjs-integration.md |
| TypeScript | typescript.md |
| 切片模式 | slices.md |
| 自动选择器 | auto-selectors.md |
| 重置状态 | reset-state.md |
| 订阅API | subscribe-api.md |
| 测试 | testing.md |
| 从v4迁移到v5 | migration-v5.md |
Best Practices
最佳实践
- Selector pattern - Always use for performance
useStore((s) => s.field) - useShallow - Wrap array/object selectors to prevent re-renders
- Separate stores - One store per domain (auth, cart, ui, theme)
- Server data elsewhere - Use TanStack Query for server state
- DevTools in dev only - Wrap devtools in process.env check
- Partialize persist - Only persist necessary fields, never tokens
- 选择器模式 - 始终使用以提升性能
useStore((s) => s.field) - useShallow - 对数组/对象选择器使用useShallow包装以防止重渲染
- 分离状态存储 - 每个领域一个状态存储(认证、购物车、UI、主题)
- 服务端数据存放在别处 - 使用TanStack Query处理服务端状态
- 仅在开发环境使用DevTools - 在process.env检查中包装devtools
- 部分持久化 - 仅持久化必要字段,绝不持久化令牌
Forbidden Patterns
禁止模式
| Pattern | Reason | Alternative |
|---|---|---|
| Global stores in App Router | Request sharing between users | Context-based stores |
| Zustand in Server Components | No React hooks in RSC | Fetch data directly |
| Persisting auth tokens | Security vulnerability | httpOnly cookies |
| Without useShallow on objects | Excessive re-renders | |
| v4 syntax | TypeScript inference broken | v5 currying |
| 模式 | 原因 | 替代方案 |
|---|---|---|
| App Router中的全局状态存储 | 用户之间的请求共享 | 基于Context的状态存储 |
| 在Server Components中使用Zustand | RSC中不支持React Hook | 直接获取数据 |
| 持久化认证令牌 | 安全漏洞 | httpOnly Cookie |
| 对对象不使用useShallow | 过度重渲染 | |
| v4语法 | TypeScript类型推断失效 | v5柯里化语法 |