zustand

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Zustand State Management

Zustand 状态管理

Overview

概述

Zustand v5 is a lightweight global state manager for React built on
useSyncExternalStore
. Requires React 18+ (uses
useSyncExternalStore
internally). When using
createWithEqualityFn
, install
use-sync-external-store
as a peer dependency. It provides type-safe stores, atomic selectors for minimal re-renders, composable middleware (persist, devtools, immer, subscribeWithSelector), and a slices pattern for large applications. Use Zustand for client-only global state; use TanStack Query for server-fetched data.
When to use: Client-side global state, persistent user preferences, complex multi-domain stores, cross-component state sharing, vanilla (non-React) state management.
When NOT to use: Server state with caching needs (use TanStack Query), single-component state (use useState), simple prop drilling scenarios.
Zustand v5是一款基于
useSyncExternalStore
的轻量级React全局状态管理器,要求React 18及以上版本(内部使用
useSyncExternalStore
)。使用
createWithEqualityFn
时,需要安装
use-sync-external-store
作为对等依赖。它提供类型安全的存储、最小化重渲染的原子选择器、可组合的中间件(persist、devtools、immer、subscribeWithSelector),以及面向大型应用的切片模式。Zustand适用于客户端专属的全局状态管理;服务器端获取的数据请使用TanStack Query。
适用场景: 客户端全局状态、持久化用户偏好、复杂多域存储、跨组件状态共享、vanilla(非React)状态管理。
不适用场景: 需要缓存的服务器状态(使用TanStack Query)、单一组件状态(使用useState)、简单的属性透传场景。

Quick Reference

快速参考

PatternAPIKey Points
Basic store
create<T>()((set) => ({...}))
Double parentheses required for TS
Atomic selector
useStore(state => state.bears)
Only re-renders when selected value changes
Multiple values
useShallow(state => ({a, b}))
Import from
zustand/react/shallow
Persist
persist(fn, { name })
localStorage with SSR hydration handling
Devtools
devtools(fn, { name })
Redux DevTools integration
SubscribeWithSelector
subscribeWithSelector(fn)
Subscribe to state slices outside React
Middleware order
devtools(persist(fn))
Outer to inner wrapping
Slices pattern
StateCreator<Combined, [], [], Slice>
Split store by domain
SSR provider
createStore
+ React Context
Per-request stores prevent data leaks
Immer
immer(fn)
Safe nested state mutations
Vanilla store
createStore
from
zustand/vanilla
Use outside React
Reset store
set(store.getInitialState())
Use
getInitialState()
for reliable reset
Derived values
useStore(s => s.items.length)
Compute in selector
Auto selectors
createSelectors(store)
Generate
store.use.field()
hooks automatically
模式API核心要点
基础存储
create<T>()((set) => ({...}))
TypeScript下必须使用双括号
原子选择器
useStore(state => state.bears)
仅当选中值变化时才会重渲染
多值选择
useShallow(state => ({a, b}))
zustand/react/shallow
导入
持久化
persist(fn, { name })
结合localStorage并支持SSR hydration处理
开发者工具
devtools(fn, { name })
集成Redux DevTools
SubscribeWithSelector
subscribeWithSelector(fn)
在React外部订阅状态切片
中间件顺序
devtools(persist(fn))
从外到内包裹
切片模式
StateCreator<Combined, [], [], Slice>
按领域拆分存储
SSR提供者
createStore
+ React Context
每个请求独立存储,避免数据泄露
Immer中间件
immer(fn)
安全的嵌套状态突变
Vanilla存储
createStore
from
zustand/vanilla
用于非React场景
重置存储
set(store.getInitialState())
使用
getInitialState()
实现可靠重置
派生值
useStore(s => s.items.length)
在选择器中计算
自动生成选择器
createSelectors(store)
自动生成
store.use.field()
钩子

Common Mistakes

常见错误

MistakeCorrect Pattern
Using
create<T>(...)
with single parentheses
Use
create<T>()(...)
double parentheses for correct TypeScript middleware inference
Selecting full state object with
useStore(state => state)
Use atomic selectors like
state.bears
or
useShallow
to avoid unnecessary re-renders
Importing
useShallow
from
zustand/shallow
Import from
zustand/react/shallow
;
zustand/shallow
exports the plain
shallow
function only
Creating new object references in selectors causing infinite loopsUse separate primitive selectors or wrap with
useShallow
from
zustand/react/shallow
Using a global singleton store with SSR or Next.jsUse the
StoreContext
provider pattern with
createStore
to prevent data leaks between requests
Tracking initial state manually for resetUse
store.getInitialState()
which Zustand provides automatically
Using Zustand for server-fetched data that needs caching and revalidationUse TanStack Query for server state; reserve Zustand for client-only global state
错误正确用法
使用单括号的
create<T>(...)
TypeScript下请使用
create<T>()(...)
双括号,以正确推断中间件类型
使用
useStore(state => state)
选择完整状态对象
使用原子选择器如
state.bears
useShallow
,避免不必要的重渲染
zustand/shallow
导入
useShallow
请从
zustand/react/shallow
导入;
zustand/shallow
仅导出普通的
shallow
函数
在选择器中创建新对象引用导致无限循环使用独立的原始类型选择器,或用
zustand/react/shallow
useShallow
包裹
在SSR或Next.js中使用全局单例存储使用
StoreContext
提供者模式结合
createStore
,避免请求间数据泄露
手动跟踪初始状态以实现重置使用Zustand自动提供的
store.getInitialState()
使用Zustand管理需要缓存和重新验证的服务器端获取数据服务器状态请使用TanStack Query;Zustand仅用于客户端专属全局状态

Delegation

任务分工

  • Store architecture and slices design: Use
    Plan
    agent to define domain boundaries, slice interfaces, and middleware composition order
  • Hydration and SSR debugging: Use
    Task
    agent to diagnose persist middleware issues, hydration mismatches, and Next.js provider setup
  • Migration from v4 to v5: Use
    Explore
    agent to find deprecated import paths, single-parentheses patterns, and legacy middleware usage
  • Testing strategy: Use
    Task
    agent to set up store mocks and test isolation patterns
  • 存储架构与切片设计:使用Plan agent定义领域边界、切片接口和中间件组合顺序
  • Hydration与SSR调试:使用Task agent排查persist中间件问题、hydration不匹配及Next.js提供者配置问题
  • 从v4迁移到v5:使用Explore agent查找已废弃的导入路径、单括号模式及旧版中间件用法
  • 测试策略:使用Task agent设置存储模拟及测试隔离模式

References

参考资料

  • Store patterns, TypeScript, and core API
  • Middleware: persist, devtools, immer, subscribeWithSelector, and custom
  • Slices pattern and large store architecture
  • SSR, Next.js, and hydration handling
  • Testing stores with Vitest and Jest
  • Migration guide: Redux, Context, and v4 to v5
  • 存储模式、TypeScript及核心API
  • 中间件:persist、devtools、immer、subscribeWithSelector及自定义中间件
  • 切片模式与大型存储架构
  • SSR、Next.js及hydration处理
  • 使用Vitest和Jest测试存储
  • 迁移指南:从Redux、Context及v4到v5