Zustand
React 状态管理的"熊之必需品"——极简 Hooks API、无 Provider、无样板代码,用不到 1 KB 的体积覆盖从小型组件到企业级应用的全部状态场景。
Zustand 是 2024-2026 年增长最快的 React 状态管理库,采用单一 Store + Hooks 选择器模型。无需 Provider 包裹,bundle 仅约 1.1KB,npm 周下载量超 3600 万,已超越 Redux 成为 React 生态下载量最高的状态管理库,是 2026 年 React 状态管理的默认选择。
Zustand
React 状态管理的"熊之必需品"——极简 Hooks API、无 Provider、无样板代码,用不到 1 KB 的体积覆盖从小型组件到企业级应用的全部状态场景。
技术简介说明
Zustand(德语"状态"之意)是由 pmndrs 维护的 React 状态管理库,由 Andrew Clark 的 former collaborator Daishi Kato 与 Paul Henschel 等核心成员共同打造。它采用单一 Store + Hooks 选择器模型管理全局状态——开发者通过 create 函数创建 store,在组件内以 useStore(selector) 的方式订阅所需状态片段,框架自动完成最小化重渲染。
Zustand 的设计哲学是"做减法":不需要 Provider 包裹、不需要 action/reducer 模板、不需要 context 嵌套。一个 store 就是一个普通的 JavaScript 对象和一组更新函数,通过 useState 一样的 Hook 在组件中使用。这种"几乎不存在"的学习成本使得 Zustand 成为 2024-2026 年增长最快的 React 状态管理方案——npm 周下载量从 2024 年初的 1200 万攀升至 2026 年中的 3600 万+,一举超越 Redux 成为 React 生态下载量最高的状态管理库。
Zustand 与 Jotai、Valtio 同属 pmndrs 生态,但定位互补:Zustand 是"单 store 自顶向下"、Jotai 是"多 atom 自底向上"、Valtio 是"Proxy 可变模式"。三者可以共存于同一个项目中,分别处理不同粒度的状态需求。截至 2026 年 7 月,Zustand 最新版本为 v5.0.14,GitHub 星标超过 58.4k。
基本信息
| 项目 | 信息 |
|---|---|
| 官网 | https://zustand.docs.pmnd.rs |
| GitHub | https://github.com/pmndrs/zustand |
| npm | https://www.npmjs.com/package/zustand |
| 最新版本 | v5.0.14(2026-05-28 发布) |
| License | MIT |
| GitHub Stars | ~58.4k |
| 周下载量 | ~3600 万 |
| Bundle Size | ~1.1 kB(gzip) |
| TypeScript | 原生支持,源码 97.9% TypeScript |
| 主要维护者 | Daishi Kato、Paul Henschel(pmndrs 团队) |
| 所属组织 | pmndrs |
| Node.js 要求 | >= 18 |
| React 要求 | >= 18(完整支持 React 19) |
快速上手
安装
# npm
npm install zustand
# yarn
yarn add zustand
# pnpm
pnpm add zustand
# bun
bun add zustand基础配置
Zustand 不需要 任何 Provider、不需要包裹 <App />。直接创建 store,直接在任何组件中使用:
// 无需全局配置,无需 Provider
// 直接创建 store 即可使用
import { create } from 'zustand'
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}))最小示例
import { create } from 'zustand'
// 1. 创建 store:state + actions 在一个函数内
interface BearState {
bears: number
increase: () => void
reset: () => void
}
const useBearStore = create<BearState>()((set) => ({
bears: 0,
increase: () => set((state) => ({ bears: state.bears + 1 })),
reset: () => set({ bears: 0 }),
}))
// 2. 在组件中使用:通过 selector 订阅所需状态
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}>One more</button>
}
// 3. 在 React 组件树中使用(无需 Provider)
function App() {
return (
<>
<BearCounter />
<Controls />
</>
)
}核心概念与架构
单一 Store 模型
Zustand 采用单 store + selector 架构。整个应用可以只有一个 store(也可以有多个独立 store),store 是一个包含状态和 actions 的 JavaScript 对象。这与 Redux 的单 store 理念一致,但省去了 reducer、action creators、dispatch 等大量样板代码。
┌─────────────────────────────────────┐
│ Zustand Store │
│ ┌───────────┐ ┌────────────────┐ │
│ │ State │ │ Actions │ │
│ │ (data) │ │ (set/reset) │ │
│ └─────┬─────┘ └───────┬────────┘ │
│ │ set(state) │ │
│ └─────────────────┘ │
│ │ │
│ useSyncExternalStore │
│ │ │
│ ┌────────────▼────────────────┐ │
│ │ Selector → Component 订阅 │ │
│ │ (最小化重渲染) │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
不可变状态 + set() 更新
Zustand 使用不可变状态模型(Immutable State Model),所有状态更新都通过 set() 函数完成,内部执行对象展开(spread)生成新引用。这与 Redux 的理念一致,但 API 极其简洁:
set(partial)— 合并部分状态set(state => partial, replace?)— 函数式更新replace: true— 完全替换状态而非合并
外部存储 + useSyncExternalStore
Zustand 的 store 是 React 外部的独立对象,不依赖 React 的 Context 机制。它使用 React 18 内置的 useSyncExternalStore Hook 实现与 React 并发模式的兼容——这是 Zustand 要求 React >= 18 的根本原因。
中间件系统
Zustand 的中间件(Middleware)是链式组合的功能增强层,采用函数式组合模式:
create(
devtools( // 4. Redux DevTools 集成
persist( // 3. 本地持久化
immer( // 2. 可变更新语法
(set, get) => ({ ... }) // 1. 基础 store
)
)
)
)
核心特性
1. 极简 API
整个核心 API 只有 create、set、get 三个函数。没有 Provider、没有 action、没有 reducer、没有 dispatch。一个 store 就是一个 Hook。
2. 无 Provider 包裹
基于 useSyncExternalStore 的外部存储模型,不需要在组件树顶层包裹任何 Context Provider。任何组件都可以直接使用 store。
3. Selector 精细订阅
通过 selector 函数精确订阅所需状态片段,框架使用 Object.is 做浅比较,只有选中值变化时才触发重渲染:
// 只订阅 count,其他状态变化不会触发此组件重渲染
const count = useStore((state) => state.count)4. 中间件生态
内置 devtools、persist、subscribeWithSelector、combine、temporal 等中间件,支持链式组合。社区提供了 immer、redux(兼容 Redux reducer)、query 等扩展中间件。
5. TypeScript 一等支持
源码 97.9% 为 TypeScript,提供完整的类型推断。v5 进一步收紧了类型安全性,setState 的 replace 参数有严格类型检查。
6. 多平台兼容
支持 React DOM、React Native、React Three Fiber(r3f)、Preact 等多种渲染器。Store 本身是纯 JavaScript 对象,也可在非 React 环境(Vue、Svelte、Vanilla JS)中使用。
7. 异步操作原生支持
actions 中可以直接使用 async/await,无需任何额外配置:
const useStore = create((set) => ({
fetchData: async () => {
const data = await api.getData()
set({ data })
},
}))8. Store 组合与切片
支持将 store 拆分为多个独立的切片(slice),每个切片管理一部分状态和 actions,适合大型应用模块化组织。
9. 持久化存储
persist 中间件内置支持 localStorage、sessionStorage、IndexedDB 等多种存储后端,支持版本迁移(migrate)和部分持久化(partialize)。
10. DevTools 集成
devtools 中间件无缝接入 Redux DevTools,支持时间旅行调试、状态快照、action 日志等。
生态图
Zustand 生态
│
┌───────────────────────┼───────────────────────┐
│ │ │
官方中间件 社区扩展 开发者工具
│ │ │
├─ devtools ├─ zustand-computed ├─ Redux DevTools
├─ persist ├─ zustand/middleware ├─ Zustand Explorer
├─ subscribeWithSelector│ (immer, redux) ├─ Chrome Extension
├─ combine ├─ zustand-x │
├─ temporal ├─ zustand-query 集成方案
│ ├─ zustand-form │
│ └─ zustand-router ├─ Next.js
│ ├─ React Native
官方调试工具 ├─ React Three Fiber
│ ├─ Remix
└─ zustand-demo ├─ Tauri
└─ Electron
核心生态包
| 包名 | 说明 |
|---|---|
zustand | 核心库 |
zustand/middleware | 官方中间件集合(devtools、persist 等) |
zustand/traditional | createWithEqualityFn(v5 迁移兼容) |
zustand/shallow | useShallow Hook(浅比较选择器) |
zustand/middleware/immer | Immer 中间件,支持可变更新语法 |
zustand/middleware/redux | Redux reducer 兼容中间件 |
适用场景
1. 中小型项目的全局状态管理
Zustand 的极简 API 和零配置特性使其成为中小型项目的首选。无需 Provider、无需样板代码,几分钟内即可完成状态管理搭建。
2. 替代 Redux 的现代方案
对于已经熟悉 Redux 但厌倦了样板代码的团队,Zustand 提供了类似的心智模型(单 store、不可变更新、DevTools)但代码量减少 70%+。
3. 跨组件共享状态
需要多个不相关组件共享同一份状态(用户认证、主题、购物车等)时,Zustand 的无 Provider 模型使得状态访问极其便捷。
4. 需要持久化的状态
persist 中间件内置支持 localStorage、IndexedDB 等,适合需要状态持久化的场景(表单草稿、用户偏好设置等)。
5. 服务端状态与缓存
结合 zustand-query 或自定义异步 actions,可以处理服务端状态缓存,适合 Next.js、Remix 等 SSR 框架。
6. 3D / Canvas / 游戏类应用
Zustand 在 React Three Fiber(r3f)社区中使用极其广泛,适合需要高频更新且不影响 React 渲染性能的场景。
7. 多 Store / 模块化架构
大型应用可以创建多个独立 store,每个 store 负责一个业务领域,避免单 store 过于庞大。
开发与工程化
TypeScript 配置
import { create } from 'zustand'
// 推荐:使用接口定义 store 类型
interface CounterState {
count: number
increment: () => void
decrement: () => void
reset: () => void
}
const useCounterStore = create<CounterState>()((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
reset: () => set({ count: 0 }),
}))Store 切片模式(Slice Pattern)
import { create } from 'zustand'
import { devtools, persist } from 'zustand/middleware'
import type { StateCreator } from 'zustand'
// 定义各切片
interface BearSlice {
bears: number
addBear: () => void
}
interface FishSlice {
fishes: number
addFish: () => void
}
// 各切片独立实现
const createBearSlice: StateCreator<
BearSlice & FishSlice,
[['zustand/devtools', never], ['zustand/persist', unknown]],
[],
BearSlice
> = (set) => ({
bears: 0,
addBear: () => set((state) => ({ bears: state.bears + 1 })),
})
const createFishSlice: StateCreator<
BearSlice & FishSlice,
[['zustand/devtools', never], ['zustand/persist', unknown]],
[],
FishSlice
> = (set) => ({
fishes: 0,
addFish: () => set((state) => ({ fishes: state.fishes + 1 })),
})
// 组合切片
const useStore = create<BearSlice & FishSlice>()(
devtools(
persist(
(...a) => ({
...createBearSlice(...a),
...createFishSlice(...a),
}),
{ name: 'animal-store' }
)
)
)测试
import { act } from 'react'
import { useBearStore } from './store'
test('should increase bears', () => {
// 重置 store 状态
act(() => useBearStore.setState({ bears: 0 }))
// 调用 action
act(() => useBearStore.getState().increase())
// 验证结果
expect(useBearStore.getState().bears).toBe(1)
})代码分割
// 动态导入 store,实现代码分割
const useHeavyStore = create(() => ({
/* 大量状态 */
}))
// 在组件中懒加载
const HeavyComponent = lazy(() => import('./HeavyComponent'))性能与安全
性能特性
| 维度 | 表现 |
|---|---|
| Bundle Size | ~1.1 kB(gzip),比 Redux 小约 7 倍 |
| 重渲染优化 | 基于 selector + Object.is 的精细订阅,只订阅部分状态时其他状态变化不触发重渲染 |
| 渲染次数 | 与 useState 几乎相同(1000 个订阅组件约 18ms) |
| 内存占用 | 极低,store 是纯 JavaScript 对象,无额外包装 |
| 并发安全 | 基于 useSyncExternalStore,完整支持 React 18+ 并发模式 |
| 服务端渲染 | 完整支持 SSR,支持流式渲染 |
性能优化要点
// ✅ 正确:使用 selector 精确订阅
const count = useStore((state) => state.count)
// ✅ 正确:使用 useShallow 避免对象引用变化
import { useShallow } from 'zustand/shallow'
const { count, text } = useStore(
useShallow((state) => ({ count: state.count, text: state.text }))
)
// ❌ 避免:在组件内创建新函数引用
const filtered = useStore((state) => state.items.filter(i => i.active))
// ✅ 改用:外部选择器函数
const selectActiveItems = (state) => state.items.filter(i => i.active)
const filtered = useStore(selectActiveItems)安全注意事项
- Zustand 的
persist中间件默认使用JSON.stringify/parse,存储数据在 localStorage 中是明文的。敏感数据需要额外加密。 persist中间件的storage选项支持自定义序列化逻辑,可以接入加密方案。- Zustand 本身不做状态校验,输入验证应在 actions 层实现。
- 避免在 store 中存储不可序列化的对象(DOM 引用、循环引用对象等)。
技术对比
横向对比表
| 特性 | Zustand | Redux Toolkit | Jotai | Valtio | MobX | Recoil |
|---|---|---|---|---|---|---|
| 模型 | 单 Store | 单 Store | 原子化 (Atom) | Proxy 可变 | 可观察对象 | 原子化 (Atom) |
| Bundle Size | ~1.1 kB | ~11 kB | ~4 kB | ~3 kB | ~16 kB | ~14 kB |
| 学习曲线 | ⭐ 极低 | ⭐⭐⭐ 中等 | ⭐⭐ 低 | ⭐ 极低 | ⭐⭐⭐ 中高 | ⭐⭐⭐ 中等 |
| Provider | 不需要 | 需要 | 不需要 | 不需要 | 不需要 | 需要 |
| 可变/不可变 | 不可变 | 不可变 | 不可变 | 可变 (Proxy) | 可变 (Observable) | 不可变 |
| TypeScript | 优秀 | 优秀 | 优秀 | 良好 | 优秀 | 良好 |
| DevTools | Redux DevTools | Redux DevTools | 独立 DevTools | Chrome Extension | MobX DevTools | Recoil DevTools |
| 中间件 | 丰富 | 丰富 | 基础 | 有限 | 丰富 | 有限 |
| SSR | ✅ | ✅ | ✅ | ✅ | ✅ | ⚠️ 有限 |
| React Native | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 并发模式 | ✅ | ✅ | ✅ | ✅ | ⚠️ | ⚠️ |
| 维护状态 | 活跃 | 活跃 | 活跃 | 活跃 | 活跃 | 已归档 |
| 周下载量 (2026) | ~3600 万 | ~600 万 | ~530 万 | ~160 万 | ~250 万 | — |
| GitHub Stars | ~58.4k | ~61k | ~21.2k | ~10.2k | ~27k | — |
选型建议
- Zustand — 大多数项目的最佳选择。API 最简单、bundle 最小、无需 Provider、适合从小组件到大型应用的完整场景。
- Redux Toolkit — 大型团队需要严格规范、时间旅行调试、完善的 DevTools 和可预测的 action/reducer 流时使用。
- Jotai — 复杂相互依赖的状态(如表单构建器、派生状态链),原子化模型更适合自底向上组合。
- Valtio — 偏好可变更新语法、类 Vue/MobX 的开发体验时使用。
- MobX — 已有 MobX 代码库的项目继续使用;新项目在 React 场景下通常优先 Zustand/Valtio。
- Recoil — 已被 Meta 归档(archived),不建议新项目使用,现有项目建议迁移至 Jotai 或 Zustand。
最佳实践
1. 使用 Selector 精确订阅
// ✅ 只订阅需要的字段
const count = useStore((state) => state.count)
// ✅ 组合多个 selector
const count = useStore(useShallow((s) => s.count))
const name = useStore(useShallow((s) => s.name))
// ❌ 避免订阅整个 store
const store = useStore() // 任何状态变化都会触发重渲染2. 将 Actions 与 State 放在一起
// ✅ 推荐:actions 和 state 在同一个 store 定义中
const useStore = create((set) => ({
count: 0,
increment: () => set((s) => ({ count: s.count + 1 })),
}))
// ❌ 避免:actions 定义在组件内部
function Counter() {
const increment = () => useStore.setState((s) => ({ count: s.count + 1 }))
}3. 使用 Immer 中间件简化深层更新
import { create } from 'zustand'
import { immer } from 'zustand/middleware/immer'
const useStore = create(
immer((set) => ({
users: [],
updateUser: (id, name) =>
set((state) => {
const user = state.users.find((u) => u.id === id)
if (user) user.name = name // 直接可变更新,Immer 自动生成不可变副本
}),
}))
)4. 使用 persist 中间件持久化状态
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
const useAuthStore = create(
persist(
(set) => ({
token: null,
setToken: (token) => set({ token }),
}),
{
name: 'auth-storage', // localStorage key
partialize: (state) => ({ // 只持久化需要的字段
token: state.token,
}),
}
)
)5. 组件外访问 Store
// 在 React 组件外部(如 API 拦截器、工具函数)访问 store
const token = useAuthStore.getState().token
useAuthStore.setState({ token: newToken })
// 订阅状态变化(如同步到其他系统)
const unsubscribe = useAuthStore.subscribe(
(state) => state.token,
(token) => {
console.log('Token changed:', token)
}
)6. v5 迁移注意事项
// ✅ 使用 useShallow 处理返回新引用的 selector
import { useShallow } from 'zustand/shallow'
const { a, b } = useStore(useShallow((s) => ({ a: s.a, b: s.b })))
// ✅ 保持 fallback 值引用稳定
const NOOP = () => {}
const action = useStore((s) => s.action ?? NOOP)
// ❌ v4 中可用但 v5 移除的写法
const data = useStore(selector, isEqual) // 自定义相等函数已移除技术局限与边界
1. 无内置派生状态
Zustand 没有像 Jotai 的 atom((get) => ...) 或 MobX 的 computed 那样的内置派生状态机制。派生状态需要在 selector 中手动计算,或在 store 中手动维护:
// 手动维护派生状态
const useStore = create((set, get) => ({
items: [],
activeCount: 0, // 需要手动同步
addItem: (item) => set((s) => ({
items: [...s.items, item],
activeCount: s.activeCount + (item.active ? 1 : 0),
})),
}))2. 无原子化组合
Zustand 是单 store 模型,不支持像 Jotai 那样自底向上组合独立的原子状态。需要原子化组合时应选择 Jotai。
3. Selector 返回新引用的陷阱
v5 严格要求 selector 返回稳定引用。每次返回新数组/对象会导致无限循环:
// ❌ 会导致无限循环
const data = useStore((s) => [s.a, s.b])
// ✅ 必须使用 useShallow
const data = useStore(useShallow((s) => [s.a, s.b]))4. 无内置时间旅行调试
Zustand 通过 devtools 中间件接入 Redux DevTools,但不像 Redux 那样原生支持完整的时间旅行(time-travel)。temporal 中间件提供有限的撤销/重做能力。
5. 大型应用需要手动组织
Zustand 不提供官方目录结构或代码组织约定。大型应用需要自行设计切片模式(slice pattern)、模块边界和 store 拆分策略。
6. 不适合纯函数式/事件溯源架构
Zustand 的 set() 是命令式的状态更新,不适合需要完整 action 日志和事件溯源(Event Sourcing)的场景。这类场景更适合 Redux。
7. React 版本限制
v5 要求 React >= 18(因为依赖 useSyncExternalStore)。如果项目仍使用 React 17,需要停留在 v4 或使用 use-sync-external-store shim。
学习资源
官方资源
- Zustand 官方文档 — 最权威的参考
- Announcing Zustand v5 — v5 发布公告
- Zustand v5 迁移指南 — 从 v4 迁移
- Zustand GitHub — 源码、Issues、Discussions
- Zustand Demo — 在线演示
教程与文章
- Zustand 5: Minimal React State Manager That Scales (2025) — 全面的 Zustand v5 教程
- Mastering Zustand — The Modern React State Manager (v4 & v5) — 从 v4 到 v5 完整指南
- React 19: State Management with Zustand — React 19 集成指南
- Why Zustand Is Quietly Winning the React State Management War in 2026 — 2026 年 Zustand 优势分析
视频
- React State Management Just Got Way Easier — Zustand 视频教程
- When to Use Zustand, Jotai, XState, or Something Else — 状态管理选型指南
对比分析
- State Management in 2026: Zustand vs Jotai vs Redux Toolkit vs Signals — 2026 全面对比
- React State Management in 2026: A Data-Driven Comparison — 数据驱动的对比分析
- Zustand vs Legend-State vs Valtio 2026 — 三库对比指南
2026 年现状
市场地位
截至 2026 年中,Zustand 已经成为 React 生态下载量最高的状态管理库,周下载量超过 3600 万次,远超 Redux Toolkit(~600 万)和 Jotai(~530 万)。在 2024-2025 年间,Zustand 完成了对 Redux 的"静默超越"——不是通过激进的营销,而是通过开发者口口相传的"简单就是好"。
社区活跃度
- GitHub Stars:58.4k(2026 年 7 月)
- Open Issues:仅 2 个(极度稳定的代码库)
- npm 周下载量:~3600 万
- 104 个正式版本发布
技术趋势
- React 19 兼容:Zustand v5 完整支持 React 19 的并发特性,包括
use()Hook 和 Server Components。 - 无重大新特性计划:v5 是一个"清理版"(cleanup release),核心 API 已经稳定。社区预期 v6 可能在 React 新特性成熟后推出。
- pmndrs 生态协同:Zustand 与 Jotai(原子化)、Valtio(Proxy)、Koota(ECS)在 pmndrs 生态中各自定位清晰,互不竞争。
- 企业采用加速:越来越多的中大型企业从 Redux 迁移到 Zustand,特别是在新项目和技术栈升级中。
- Signals 的潜在竞争:Preact Signals 和 TC39 Signals Proposal 是 2026 年的新竞争者,但目前 Zustand 的生态成熟度和社区规模仍占据绝对优势。
选型结论
Zustand 是 2026 年 React 状态管理的默认选择。除非你有特殊需求(原子化组合 → Jotai、Proxy 可变 → Valtio、严格规范 → Redux Toolkit),否则 Zustand 是最简单、最高效的起点。
📅 文档更新时间:2026-07-07
📦 数据来源:GitHub、npm、pmndrs 官方博客、社区对比文章
🔗 基于 Zustand v5.0.14 编写