mcpField
N
nextjs-zustand

nextjs-zustand

github.com/fusengine开发3474 次安装2 周前更新
代码仓库

关于 nextjs-zustand

nextjs-zustand 是面向 Next.js 16 App Router 项目的 Zustand v5 客户端状态管理技能。它强调通过 Context 隔离请求状态,并说明 SSR 水合、持久化中间件及 TypeScript 组织方式。

主要功能

  1. 01采用 Zustand v5 currying 语法
  2. 02使用 Context 隔离 App Router 状态
  3. 03组合 devtools、persist 与 immer
  4. 04处理持久化状态的手动水合
  5. 05用 useShallow 优化选择器
  6. 06提供按功能组织文件的建议

适用场景

  1. 01为 Client Components 管理共享 UI 状态
  2. 02在 App Router 中建立请求隔离的 store
  3. 03持久化主题、购物车等客户端状态
  4. 04避免 SSR 与客户端水合不一致

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/fusengine/agents --skill nextjs-zustand

安装后在 Claude Code 中输入/nextjs-zustand确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
auto-selectors.md
hydration.md
installation.md
middleware.md
migration-v5.md
nextjs-integration.md
reset-state.md
slices.md
store-patterns.md
subscribe-api.md
testing.md
typescript.md

详细介绍

在 Next.js 16 App Router 中实现 Zustand v5 客户端状态管理:v5 柯里化语法(`create()((set) => ({...}))`)、基于 Context 的 store(使用 `zustand/vanilla` 中的 `createStore` 和 `useRef` 构建;在 App Router 中这是必需的,可避免不同请求之间的状态泄漏——绝不要使用全局 store),以及中间件组合(devtools → persist → immer,顺序会影响 TypeScript 类型)。

介绍 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:

  1. fuse-ai-pilot:explore-codebase - 分析现有 store 和状态模式
  2. fuse-ai-pilot:research-expert - 通过 Context7/Exa 验证最新的 Zustand v5 文档
  3. 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 包装器

关键规则

  1. 仅限客户端组件 - 绝不要在服务端组件中使用 Zustand
  2. App Router 使用 Context 模式 - 避免全局 store(隔离请求)
  3. 数组/对象使用 useShallow - 避免不必要的重新渲染
  4. persist 使用 skipHydration - SSR 兼容所必需
  5. 使用 v5 柯里化语法 - create<State>()((set) => ({...}))
  6. 遵循 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() 创建 store50
store.interface.tsTypeScript 接口30
store-provider.tsxContext Provider(App Router)40
use-store.ts带选择器的自定义 Hook20

核心概念

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 Routernextjs-integration.md
TypeScripttypescript.md
Slices 模式slices.md
自动选择器auto-selectors.md
重置状态reset-state.md
订阅 APIsubscribe-api.md
测试testing.md
从 v4 迁移到 v5migration-v5.md

最佳实践

  1. 选择器模式 - 始终使用 useStore((s) => s.field) 以提升性能
  2. useShallow - 使用 useShallow 包装数组/对象选择器,避免重新渲染
  3. 分离 Store - 每个领域使用一个 Store(auth、cart、ui、theme)
  4. 将服务端数据存放在其他位置 - 使用 TanStack Query 管理服务端状态
  5. 仅在开发环境使用 DevTools - 使用 process.env 检查包裹 devtools
  6. 精简持久化内容 - 只持久化必要字段,绝不持久化令牌

禁止的模式

模式原因替代方案
在 App Router 中使用全局 Store用户之间共享请求基于 Context 的 Store
在 Server Components 中使用 ZustandRSC 中没有 React hooks直接获取数据
持久化认证令牌安全漏洞httpOnly cookies
对象选择器未使用 useShallow过度重新渲染useShallow(selector)
v4 语法TypeScript 类型推断失效v5 柯里化语法 create<T>()()

评论

支持 Markdown