你还记得第一次写 React 项目时,为了实现一个简单的“待办事项”功能,被迫引入 Redux、配置 store、写 action creators、搞 reducers、连 connect……最后发现:
“我只是想勾个 checkbox 而已,为什么要动用三军?”
时代变了。
如今,我们不再需要为“状态”而向复杂妥协。
有一个轻如鸿毛、却强如引擎的工具,正在悄悄改变 React 开发者的日常 ——
👉 Zustand —— 中文谐音“足矣”,仿佛在说:“有我,就够了。”
🧩 一、React 状态管理的进化史:从“造火箭”到“骑单车”
让我们先回顾一下 React 状态管理的三个时代:
1.0 时代:Redux 统治天下
- ✅ 功能强大,适合大型项目
- ❌ 模板代码太多,“搬砖感”强烈
- 📦 配置成本高,新手劝退率 90%
就像你要去便利店买瓶水,结果被要求先考驾照、买辆车、建条公路。
2.0 时代:Context + useReducer
- ✅ 官方方案,无需第三方库
- ❌ 性能问题频出,容易引发全量重渲染
- 🔁 状态更新像“广播”,谁都在听,谁都不能不听
3.0 时代:Zustand 登场 —— 极简主义的胜利
它不做加法,而是做减法:
“状态管理的本质,不是组织代码结构,而是让数据流动得更自然。”
于是,Zustand 带来了三个字:
🎯 简单、直接、自由
💡 二、Zustand 的核心理念:把状态还给开发者
Zustand 不是另一个“框架”,它更像是一个 状态管理的“最小可行产品”(MVP)。
它的设计哲学可以总结为四句话:
- 状态就是一个 JavaScript 对象
- 修改状态就是调用一个函数
- 全局共享?不需要 Context 传递
- 类型安全?天生支持 TypeScript
它解决了什么痛点?
| 传统方式的问题 | Zustand 如何解决 |
|---|---|
| 要写 Action Type、Reducer 分别处理逻辑 | 直接在 store 里写函数 |
| 跨组件传状态要层层透传或用 Context | store 全局可访问 |
更新状态要 dispatch(action) | 直接调用 store.toggleTodo(id) |
| 持久化要手动存 localStorage | 内置 middleware 支持持久化 |
🛠️ 三、举个例子:一个 Todo 应用的“极简革命”
假设我们要做一个待办事项应用。需求很简单:
- 添加任务
- 切换完成状态
- 删除任务
- 关闭页面后数据不丢失
换成以前,你可能已经开始想:“要不要拆模块?要不要抽象 action?”
而在 Zustand 的世界里,这一切变得像写普通函数一样自然。
✅ 你的 Store 长这样:
const useTodoStore = create<TodoState>()(
persist(
(set) => ({
todos: [],
addTodo: (text) =>
set((state) => ({
todos: [...state.todos, { id: Date.now(), text, completed: false }],
})),
toggleTodo: (id) =>
set((state) => ({
todos: state.todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
),
})),
removeTodo: (id) =>
set((state) => ({
todos: state.todos.filter((todo) => todo.id !== id),
})),
}),
{ name: 'todo-storage' }
)
);
看到了吗?没有 dispatch,没有 reducer switch,没有 connect。
所有操作都是同步函数调用,逻辑清晰到几乎可以朗读出来。
“当我点击添加时,就往 todos 数组里 push 一条新数据。”
—— 这不正是我们最初想要的编程体验吗?
🔌 四、persist 中间件:让数据“记住自己”
最惊艳的是这一行:
{ name: 'todo-storage' }
加上这个配置,你的 todos 就自动存进了 localStorage。
刷新页面?数据还在。
关机重启?照样回来。
这不是魔法,而是 “合理默认值” + “极简 API” 的胜利。
你可以把它理解为:
Zustand 说:“我知道你迟早要用持久化,所以我提前帮你装好了插座,插上就行。”
而且它还是类型安全的!你在 TypeScript 中使用 useTodoStore,编辑器能自动推导出所有字段和方法,不会有 any 的尴尬。
🎣 五、基于 Hooks 的思想重构状态管理
Zustand 最深刻的革新,其实是它的架构思想。
它不像 Redux 是“类 Flux 架构”,而是完全拥抱了 React 的现代范式 —— Hooks 思维。
这意味着:
- Store 可以像
useState一样按需使用 - 不再需要 Provider 套来套去
- 组件只订阅它关心的状态片段(自动 GC)
- 可以轻松拆分多个小 store,避免“大仓库综合症”
就像你不会因为要做一道菜就建个中央厨房,
你也不该因为几个状态就搭一套复杂的管理系统。
Zustand 让“全局状态”变得像 useState 一样轻量,却又具备跨组件能力。
🆚 六、Zustand vs 其他方案:为什么越来越多人选择它?
| 方案 | 包体积 | 学习成本 | 类型支持 | 适用场景 |
|---|---|---|---|---|
| Redux Toolkit | ~7KB | 高 | 好 | 超大型项目,需严格追踪 |
| Context | 0 | 中 | 差 | 小型共享状态 |
| Recoil/Jotai | ~5KB | 中 | 好 | 原子化状态管理 |
| Zustand | ~4.5KB | 极低 | 极好 | 绝大多数中小型项目 |
GitHub 上 zustand 的 trending 曲线在过去两年一路飙升,不是偶然。
它击中了一个关键空白点:
“我需要一个比 Context 更强大、比 Redux 更轻便的方案。”
而 Zustand 正好站在那个黄金平衡点上。
🧠 七、我的思考:状态管理的未来是“去架构化”
随着 React Server Components、Suspense、Signals 等新范式的兴起,
我们越来越意识到:
状态本身不该成为开发负担。
Zustand 的流行,反映了一种趋势:
开发者不再愿意为“管理状态”而花大量时间设计架构。
我们想要的是:专注业务逻辑,而不是组织代码结构。
这也是为什么越来越多的新项目(包括 Vercel、Turborepo 的周边工具)都开始采用 Zustand。
因为它不做多余的事,只做一件事,并且做到极致:
让状态流动得更自然一点。
🚀 八、如何开始使用 Zustand?
安装只需一行:
npm install zustand
然后创建你的第一个 store:
import { create } from 'zustand';
interface BearState {
bears: number;
increase: () => void;
}
const useBearStore = create<BearState>((set) => ({
bears: 0,
increase: () => set((state) => ({ bears: state.bears + 1 })),
}));
在组件中使用:
function BearCounter() {
const { bears } = useBearStore();
return <h1>{bears} 只熊</h1>;
}
function Controls() {
const { increase } = useBearStore();
return <button onClick={increase}>喂食一只熊</button>;
}
就这么简单。没有仪式感,只有生产力。
🌈 结语:有时候,少就是多
在这个“微服务、中间件、DSL”满天飞的时代,
Zustand 像是一股清流,提醒我们:
技术的终极目标不是炫技,而是让人更自由地表达想法。
当你不再纠结“这个 action 该怎么命名”,
当你可以直接写下“addTodo”并立刻生效,
那一刻,你会感受到一种久违的——
编程的纯粹快乐。
如果你也曾被状态管理折磨过,
如果你也渴望一种更轻盈的开发方式,
不妨试试 Zustand。
也许,它真的就是你一直在找的那个答案。
#React #Zustand #状态管理 #TypeScript #前端开发 #掘金精品 #架构设计 #useStore #极简主义