Zustand 实战总结
Zustand 是一个轻量、无样板代码(boilerplate)的 React 状态管理库。相比 Redux 更简单,相比 Context 更高效,非常适合中小型到中大型项目。
# 一、Zustand 核心理念
# ✅ 设计哲学
- 极简 API
- 基于 Hooks
- 无 Provider(默认)
- 支持中间件
- 支持 TS 友好
核心思想:
用一个全局 store + hook 选择性订阅状态
# 二、基础入门
# 1️⃣ 安装
npm install zustand
1
# 2️⃣ 创建第一个 Store
import { create } from 'zustand'
const useCounterStore = create((set) => ({
count: 0,
increase: () => set((state) => ({ count: state.count + 1 })),
decrease: () => set((state) => ({ count: state.count - 1 })),
}))
1
2
3
4
5
6
7
2
3
4
5
6
7
# 3️⃣ 组件中使用
function Counter() {
const { count, increase, decrease } = useCounterStore()
return (
<>
<div>{count}</div>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</>
)
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- ✔ 自动订阅
- ✔ 组件卸载自动取消订阅
- ✔ 无 Provider
# 三、进阶核心技巧
# 🎯 1. 精准订阅(避免无效渲染)
const count = useCounterStore((state) => state.count)
1
只监听 count,其他字段变化不会触发重渲染。
# 搭配浅比较
import { shallow } from 'zustand/shallow'
const { count, increase } = useCounterStore(
(state) => ({ count: state.count, increase: state.increase }),
shallow
)
1
2
3
4
5
6
2
3
4
5
6
# 🎯 2. 异步操作(请求接口)
const useUserStore = create((set) => ({
user: null,
loading: false,
fetchUser: async () => {
set({ loading: true })
const res = await fetch('/api/user')
const data = await res.json()
set({ user: data, loading: false })
}
}))
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- ✔ Zustand 不限制 async
- ✔ 无 thunk / saga 概念
# 🎯 3. 中间件使用
# persist(本地存储)
import { persist } from 'zustand/middleware'
const useStore = create(
persist(
(set) => ({
theme: 'light',
toggle: () => set((s) => ({ theme: s.theme === 'light' ? 'dark' : 'light' })),
}),
{
name: 'app-storage',
}
)
)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# devtools(调试)
import { devtools } from 'zustand/middleware'
const useStore = create(
devtools((set) => ({
count: 0,
inc: () => set((s) => ({ count: s.count + 1 }), false, 'inc')
}))
)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
可在 Redux DevTools 中查看。
# 🎯 4. 拆分模块(大型项目)
推荐结构:
store/
├── index.ts
├── user.ts
├── cart.ts
└── theme.ts
1
2
3
4
5
2
3
4
5
# 模块合并
import { create } from 'zustand'
import { createUserSlice } from './user'
import { createCartSlice } from './cart'
export const useStore = create((...a) => ({
...createUserSlice(...a),
...createCartSlice(...a),
}))
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- ✔ 类似 Redux slice
- ✔ 更清晰
- ✔ 可维护性强
# 四、高级实战技巧
# 🔥 1. get() 读取最新状态
const useStore = create((set, get) => ({
count: 0,
double: () => {
const current = get().count
set({ count: current * 2 })
}
}))
1
2
3
4
5
6
7
2
3
4
5
6
7
# 🔥 2. subscribe 监听(非组件环境)
const unsubscribe = useStore.subscribe(
(state) => state.count,
(count) => console.log('count changed:', count)
)
1
2
3
4
2
3
4
适用于:
- 日志系统
- websocket
- 外部模块监听
# 🔥 3. immer 中间件(复杂对象)
import { immer } from 'zustand/middleware/immer'
const useStore = create(
immer((set) => ({
user: { name: '', age: 0 },
updateName: (name: string) =>
set((state) => {
state.user.name = name
}),
}))
)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- ✔ 可变写法
- ✔ 内部自动 immutable
# 🔥 4. 重置 Store
const initialState = { count: 0 }
const useStore = create((set) => ({
...initialState,
reset: () => set(initialState),
}))
1
2
3
4
5
6
2
3
4
5
6
# 五、性能优化总结
# ✅ 必做
- 使用 selector
- 使用 shallow
- 拆分 store
- 避免大对象直接返回
# ❌ 避免
- 整个 state 解构
- 在 store 里写复杂 UI 状态
- 所有状态放一个 store
# 六、Zustand vs Redux 对比
| 对比 | Zustand | Redux |
|---|---|---|
| 学习成本 | 低 | 高 |
| 模板代码 | 少 | 多 |
| 中间件 | 支持 | 强 |
| 适合项目 | 中小/中大型 | 中大型 |
# 七、企业级最佳实践
# 1️⃣ 状态分层
- UI状态(本地)
- 全局共享状态(Zustand)
- 服务器状态(React Query)
推荐组合:
- Zustand + React Query
- Zustand + Vite
- Zustand + Next.js
# 2️⃣ 不要滥用全局状态
判断标准:
- 多组件共享?
- 是否跨页面?
- 是否需要缓存?
否则使用 useState。
# 八、常见坑总结
- ⚠ StrictMode 下初始化两次
- ⚠ persist 需要处理版本升级
- ⚠ SSR 需避免状态污染
- ⚠ 异步并发注意覆盖问题
# 九、实战项目结构示例
src/
├── store/
│ ├── authStore.ts
│ ├── productStore.ts
│ └── index.ts
├── hooks/
├── pages/
└── services/
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 🔟 终极总结
Zustand 适合:
- ✔ 追求简单
- ✔ 不想写 reducer
- ✔ 不想配置复杂中间件
- ✔ 希望极致开发体验
一句话总结:
小而美,够用且强大。
上次更新: 2026/02/25, 10:38:50