Skip to content
安装与快速开始

安装与快速开始

Zustand 是一个轻量、快速、可扩展的 React 状态管理库。它基于发布-订阅模式,API 极其简洁,无需 Provider 包裹,选择器机制天然避免无效重渲染。

官方文档:Zustand | GitHub 名称由来:Zustand 是德语 “state”(状态)的意思。


前置条件

  • React:16.8+(需支持 Hooks)
  • Node.js:16.0 或更高版本
  • TypeScript:可选,但 Zustand 对 TS 支持极好,推荐使用

Zustand 本身不依赖 React——它的 vanilla API 可在任何 JS 环境中使用(浏览器、Node.js、React Native 等)。


安装

npm install zustand
# 或
yarn add zustand
# 或
pnpm add zustand

包体积极小:~2KB gzipped(v4),v5 约 ~1.1KB gzipped。


版本说明

版本 重大变化 推荐
v5.x 移除 default 导出(需命名导入 create);persistsubscribeWithSelector 不再默认导出;中间件能力内聚优化 ✅ 新项目推荐
v4.x 完善的 TypeScript 支持、useShallow 稳定 存量项目维护
v3.x 早期版本,API 差异大 ❌ 不再推荐

🚨 陷阱:v5 起 import create from 'zustand' 失效,必须 import { create } from 'zustand'persistdevtoolssubscribeWithSelector 也需从具名导出导入。


第一个 Store

import { create } from 'zustand';

// 1. 定义 Store 类型(推荐)
interface BearStore {
  bears: number;
  increase: () => void;
  reset: () => void;
}

// 2. 创建 Store
const useBearStore = create<BearStore>((set) => ({
  bears: 0,
  increase: () => set((state) => ({ bears: state.bears + 1 })),
  reset: () => set({ bears: 0 }),
}));

在组件中使用

function BearCounter() {
  // 使用选择器精确订阅 bears 字段
  const bears = useBearStore((state) => state.bears);
  return <h1>{bears} bears around here...</h1>;
}

function Controls() {
  // 订阅 action(action 引用不变,不会触发不必要的重渲染)
  const increase = useBearStore((state) => state.increase);
  return <button onClick={increase}>Add a bear</button>;
}

✅ 关键点:无需 Provider! 组件直接通过 useBearStore 订阅状态,这是 Zustand 和 Redux 最大的体验差异。


三秒速览:与 Redux 对比

特性 Zustand Redux Toolkit
Provider 包裹 ❌ 不需要 ✅ 必须
创建 Store create((set) => ({...})) configureStore({reducer: {...}})
读取状态 useStore(s => s.field) useSelector(s => s.field)
修改状态 set({ field: val }) dispatch(action)
不可变更新 手动(或配合 Immer) 内置 Immer
异步 在 action 里直接写 async createAsyncThunk
包体积 ~2KB ~11KB
DevTools devtools 中间件 内置
学习曲线 极低

项目结构建议

src/
├── stores/
│   ├── useBearStore.ts       # 一个 Store 一个文件
│   ├── useUserStore.ts
│   └── useCartStore.ts
├── components/
│   └── ...

Zustand 推崇多 Store 模式——按功能域拆分,而不是像 Redux 那样把所有状态塞进单一 Store。每个 Store 文件通常导出以 use 开头的 hook:

// stores/useUserStore.ts
import { create } from 'zustand';

interface UserState {
  user: User | null;
  setUser: (user: User) => void;
  logout: () => void;
}

export const useUserStore = create<UserState>((set) => ({
  user: null,
  setUser: (user) => set({ user }),
  logout: () => set({ user: null }),
}));

💡 最佳实践:Store 文件命名以 use 开头(useXxxStore),与 React Hook 命名规范一致,代码阅读时一眼就能认出这是一个 Zustand Store。


在组件外使用

Zustand Store 本身就是发布-订阅对象,可以在任何地方读/写:

// ✅ 在 React 组件外
useBearStore.getState().increase();          // 读取状态
useBearStore.setState({ bears: 10 });       // 直接设置

// ✅ 在普通函数中
function saveToServer() {
  const { bears } = useBearStore.getState();
  fetch('/api/bears', { method: 'POST', body: JSON.stringify({ bears }) });
}

💡 最佳实践:这一特性让 Zustand 天然适合作为事件总线使用——比如在 WebSocket 回调、定时器、fetch 拦截器中直接操作 Store。


快速检查清单

  • 安装成功:npm ls zustand 能看到版本号
  • 创建了第一个 Store,能在组件中读取和修改状态
  • 理解 createsetget 三个核心 API
  • 理解选择器 useStore(s => s.field) 的写法
  • 知道在组件外可以用 useStore.getState() / useStore.setState()
  • TypeScript 类型已正确定义