关于 nextjs-zustand
nextjs-zustand 是面向 Next.js 16 App Router 项目的 Zustand v5 客户端状态管理技能。它强调通过 Context 隔离请求状态,并说明 SSR 水合、持久化中间件及 TypeScript 组织方式。
主要功能
- 01采用 Zustand v5 currying 语法
- 02使用 Context 隔离 App Router 状态
- 03组合 devtools、persist 与 immer
- 04处理持久化状态的手动水合
- 05用 useShallow 优化选择器
- 06提供按功能组织文件的建议
适用场景
- 01为 Client Components 管理共享 UI 状态
- 02在 App Router 中建立请求隔离的 store
- 03持久化主题、购物车等客户端状态
- 04避免 SSR 与客户端水合不一致
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ fusengine/ agents --skill nextjs-zustand安装后在 Claude Code 中输入/nextjs-zustand确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/auto-selectors.mdhydration.mdinstallation.mdmiddleware.mdmigration-v5.mdnextjs-integration.mdreset-state.mdslices.mdstore-patterns.mdsubscribe-api.mdtesting.mdtypescript.md详细介绍
介绍 persist 中间件的 skipHydration,以及如何在 useEffect 中手动重新水合,以避免 SSR 不匹配;使用 useShallow 处理数组/对象选择器;并采用 SOLID 文件组织方式(store.ts、store-provider.tsx、use-store.ts)。明确说明 Zustand 仅用于客户端组件——绝不在服务端组件中使用(应直接在那里获取数据),也绝不用于持久化身份验证令牌(应使用 httpOnly cookies)。不涉及服务端状态缓存(参见 nextjs-tanstack-query)。
Next.js 16 中的 Zustand
基于 React 18+ useSyncExternalStore 的简洁、可扩展状态管理。
Agent 工作流(强制)
进行任何实现之前,必须并行启动 3 个 Agent,每个都单独调用一次 Agent,并指定一个 name:
- fuse-ai-pilot:explore-codebase - 分析现有 store 和状态模式
- fuse-ai-pilot:research-expert - 通过 Context7/Exa 验证最新的 Zustand v5 文档
- mcp__context7__query-docs - 检查中间件和 TypeScript 模式
实现后,运行 fuse-ai-pilot:sniper 进行验证。
概述
适用场景
- 在 Next.js App Router 应用中管理客户端状态
- 需要在客户端组件之间共享全局状态
- 将状态持久化到 localStorage/sessionStorage
- 构建 UI 状态(模态框、侧边栏、主题、购物车)
- 用于复杂状态时替代 React Context
为什么选择 Zustand v5
| 特性 | 优势 |
|---|---|
| 极简 API | 简单的 create() 函数,无需样板代码 |
| 原生支持 React 18 | 使用 useSyncExternalStore,无需填充程序 |
| TypeScript 优先 | 使用柯里化模式实现完整类型推断 |
| 中间件栈 | 可组合 devtools、persist、immer |
| 包体积 | gzip 压缩后约 2KB,是体积最小的状态库 |
| 无需 Provider | 可直接访问 store,无需 Context 包装器 |
关键规则
- 仅限客户端组件 - 绝不要在服务端组件中使用 Zustand
- App Router 使用 Context 模式 - 避免全局 store(隔离请求)
- 数组/对象使用 useShallow - 避免不必要的重新渲染
- persist 使用 skipHydration - SSR 兼容所必需
- 使用 v5 柯里化语法 -
create<State>()((set) => ({...})) - 遵循 SOLID 路径 - store 放在
modules/[feature]/src/stores/
SOLID 架构
模块结构
按功能模块组织 store:
modules/cores/stores/- 共享 store(主题、UI)modules/auth/src/stores/- 身份验证状态modules/cart/src/stores/- 购物车状态modules/[feature]/src/interfaces/- Store 类型
文件组织
| 文件 | 用途 | 最大行数 |
|---|---|---|
store.ts | 使用 create() 创建 store | 50 |
store.interface.ts | TypeScript 接口 | 30 |
store-provider.tsx | Context Provider(App Router) | 40 |
use-store.ts | 带选择器的自定义 Hook | 20 |
核心概念
Store 创建(v5 语法)
TypeScript 类型推断需要使用双括号。柯里化模式可确保完整的类型安全。
基于 Context 的 Store
对于 Next.js App Router,应将 store 包装在 Context 中,以防请求之间共享状态。使用 zustand/vanilla 中的 createStore,并通过 useRef 初始化。
中间件组合
按以下顺序叠加中间件:devtools → persist → immer。顺序会影响 TypeScript 类型。
水合处理
在 persist 中间件中使用 skipHydration: true。在 useEffect 中手动重新水合,以避免 SSR 不匹配。
参考指南
| 需求 | 参考 |
|---|---|
| 初始设置 | installation.md |
| Store 模式 | store-patterns.md |
| SSR/水合 | hydration.md |
| 中间件 | middleware.md |
| Next.js App Router | nextjs-integration.md |
| TypeScript | typescript.md |
| Slices 模式 | slices.md |
| 自动选择器 | auto-selectors.md |
| 重置状态 | reset-state.md |
| 订阅 API | subscribe-api.md |
| 测试 | testing.md |
| 从 v4 迁移到 v5 | migration-v5.md |
最佳实践
- 选择器模式 - 始终使用
useStore((s) => s.field)以提升性能 - useShallow - 使用
useShallow包装数组/对象选择器,避免重新渲染 - 分离 Store - 每个领域使用一个 Store(auth、cart、ui、theme)
- 将服务端数据存放在其他位置 - 使用 TanStack Query 管理服务端状态
- 仅在开发环境使用 DevTools - 使用 process.env 检查包裹 devtools
- 精简持久化内容 - 只持久化必要字段,绝不持久化令牌
禁止的模式
| 模式 | 原因 | 替代方案 |
|---|---|---|
| 在 App Router 中使用全局 Store | 用户之间共享请求 | 基于 Context 的 Store |
| 在 Server Components 中使用 Zustand | RSC 中没有 React hooks | 直接获取数据 |
| 持久化认证令牌 | 安全漏洞 | httpOnly cookies |
| 对象选择器未使用 useShallow | 过度重新渲染 | useShallow(selector) |
| v4 语法 | TypeScript 类型推断失效 | v5 柯里化语法 create<T>()() |