Zustand 是什么?
Zustand 是一个轻量级的 React 状态管理库
,由开发者社区(如 Poimandres 团队)维护。它的核心思想是通过简单的 API 实现全局状态的创建、订阅和更新
,同时兼容 React 的并发模式(Concurrent Mode)
。Zustand 的核心理念是“去中心化”
,允许开发者以更灵活的方式管理状态
。
Zustand 的优点
1. 简洁轻量
-
极简的 API(如 create、set、get),学习成本低,代码量少。
-
不需要像 Redux 那样定义 actions、reducers、store 的模板代码。
2. 高性能
-
自动依赖追踪,通过选择器(selectors)优化组件渲染,避免不必要的更新。
-
直接修改状态(类似 MobX),无需 immutable updates(不可变更新)。
3. 灵活性和兼容性
-
天然支持 React Hooks,无缝集成函数式组件。
-
支持中间件(如 persist 持久化、devtools 调试工具)。
-
兼容 React 18 并发模式。
4. 包体积小
- 压缩后仅 1-2KB,远小于 Redux(约 7KB)和 MobX(约 15KB)。
5. TypeScript 友好
- 天生支持 TypeScript,类型推断清晰。
Zustand 的缺点
1. 生态相对年轻
- 插件和中间件数量不如 Redux 或 MobX 丰富。
2. 缺乏强约束
-
灵活性的代价是可能写出不规范的代码(如直接在组件中随意修改状态)。
-
对大型项目的架构规范需要团队自行制定。
3. 调试工具较弱
- 虽然支持 Redux DevTools,但调试体验略逊于 Redux。
与 Redux、MobX、Model 的区别与优势
1. vs Redux
2. vs MobX
3. vs 自建 Model(如 Context API)
总结:
1. Zustand 的核心优势
-
简单高效:适合中小型项目快速迭代,避免过度设计。
-
轻量灵活:不强制规范,开发者可自由选择架构模式。
-
现代化设计:拥抱 React Hooks 和 TypeScript,契合最新技术趋势。
2. 适用场景:
-
新项目启动,追求开发效率。
-
需要轻量级状态管理,避免 Redux/MobX 的复杂度。
-
团队偏好函数式编程,希望减少模板代码。
3. 不适用场景:
-
超大型项目需要严格架构规范(此时 Redux 更合适)。
-
需要复杂响应式逻辑(此时 MobX 更合适)。
🌰
以下是一个使用 Zustand 的完整示例,包含常见的状态管理场景(如计数器、待办事项列表、异步操作),并附带详细注释:
// 安装依赖:npm install zustand
// ================= 1. 创建 Store =================
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'
// 定义类型(TypeScript)
interface Todo {
id: number
text: string
completed: boolean
}
interface CounterState {
count: number
increment: () => void
decrement: () => void
}
interface TodoState {
todos: Todo[]
addTodo: (text: string) => void
toggleTodo: (id: number) => void
fetchTodos: () => Promise<void>
}
// 创建计数器 Store
const useCounterStore = create<CounterState>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}))
// 创建待办事项 Store(带持久化和异步操作)
const useTodoStore = create<TodoState>()(
persist( // 使用持久化中间件
(set, get) => ({
todos: [],
addTodo: (text: string) => {
const newTodo: Todo = {
id: Date.now(),
text,
completed: false
}
set({ todos: [...get().todos, newTodo] })
},
toggleTodo: (id: number) => {
set({
todos: get().todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
})
},
// 模拟异步获取数据
fetchTodos: async () => {
const response = await fetch('https://dummyjson.com/todos?limit=3')
const data = await response.json()
set({ todos: data.todos.slice(0, 3) }) // 取前3条
}
}),
{
name: 'todo-storage', // localStorage 的 key
storage: createJSONStorage(() => localStorage), // 存储方式
}
)
)
// ================= 2. 在组件中使用 =================
import { useEffect } from 'react'
// 计数器组件
function Counter() {
const { count, increment, decrement } = useCounterStore()
return (
<div>
<h2>Counter: {count}</h2>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
)
}
// 待办事项组件
function TodoList() {
const { todos, addTodo, toggleTodo, fetchTodos } = useTodoStore()
const [inputText, setInputText] = useState('')
// 初始化时获取数据
useEffect(() => {
fetchTodos()
}, [])
return (
<div>
<h2>Todos ({todos.length})</h2>
<input
value={inputText}
onChange={(e) => setInputText(e.target.value)}
/>
<button onClick={() => {
addTodo(inputText)
setInputText('')
}}>
Add Todo
</button>
<ul>
{todos.map(todo => (
<li
key={todo.id}
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
onClick={() => toggleTodo(todo.id)}
>
{todo.text}
</li>
))}
</ul>
</div>
)
}
// ================= 3. 主组件 =================
export default function App() {
return (
<div>
<h1>Zustand Demo</h1>
<Counter />
<TodoList />
</div>
)
}
示例功能说明
1. 计数器功能
-
使用 useCounterStore 管理计数状态
-
支持增减操作(直接通过 set 更新状态)
2. 待办事项功能
-
使用 useTodoStore 管理待办事项
-
包含添加、切换完成状态功能
-
使用 persist 中间件实现 localStorage 持久化
-
模拟异步数据获取(通过 fetchTodos)
3. 特性展示
-
状态分离:多个独立的 store
-
中间件:持久化(刷新页面后数据保留)
-
异步操作:通过 async/await 处理
-
TypeScript:完整的类型安全
4. 运行效果
-
计数器可以自由增减
-
输入文字后点击 “Add Todo” 添加事项
-
点击事项切换完成状态(文字划线效果)
-
页面刷新后数据依然保留(持久化生效)
-
初始化时会加载模拟的异步数据
-