一、 Zustand 是什么?和 Redux 有什么区别?
1. Zustand 是什么?
Zustand 是一个轻量、现代化、基于 React Hook 的状态管理库,由 Preact 团队开发。
它简化了 Redux 中的复杂流程,提供了更简洁、更直观的状态管理方式,是目前 React 社区中最受欢迎的状态管理工具之一。
2.Zustand 解决了什么问题?(对比传统 React 状态管理)
场景 | 传统 React 方式(props/context) | Zustand 方式 |
---|---|---|
多个组件共享状态 | 需要层层传递 props,或使用 Context API | 所有组件直接访问 store |
状态更新后组件刷新 | 需要手动触发或使用 useEffect | 自动刷新,无需手动处理 |
状态管理复杂度 | 随着项目变大变得难以维护 | store 模块化,便于维护 |
异步操作 | 需要配合 useEffect 或其他库 | 可以直接在 store 中写异步逻辑 |
3. Zustand 与 Redux 的对比
功能/特点 | Redux | Zustand |
---|---|---|
创建 Store | 需要 createStore 、reducer 、action |
直接 create((set) => ({ ... })) |
修改状态 | 需要 dispatch(action) |
直接调用方法如 increment() |
是否需要 Provider | 是,需要包裹 <Provider> |
否,直接使用 Hook |
异步操作 | 需配合 redux-thunk 或 redux-saga |
可直接在 store 中写 async/await |
状态更新方式 | 不可变更新(state => newState ) |
支持不可变更新,也可以直接赋值 |
学习成本 | 较高(需要理解 action、reducer、dispatch) | 极低(直接写状态和方法) |
TypeScript 支持 | 支持,但配置较复杂 | 支持良好,类型推导更简单 |
调试工具 | 支持 Redux DevTools | 支持 Redux DevTools(通过中间件) |
体积 | 约 2KB(+ thunk/saga) | 压缩后约 1KB |
4.Zustand 的定位
- 不是 Redux 的替代品 ,而是简化版的状态管理方案。
- 适合大多数中小型项目,尤其是不想写冗长
reducer
和action
的开发者。 - 如果你只需要共享状态、修改状态、监听状态变化,Zustand 是比 Redux 更轻、更快的选择。
5. Zustand 的核心使用流程
创建 store(状态 + 修改方法) → 在组件中通过 Hook 使用 store → 在 UI 中使用状态和方法
二、 基础:如何写一个 Zustand Store?
1. 创建 Store 文件
在 src/store/countStore.js
中创建一个 store:
js
// 引入 zustand 的 create 函数,用于创建 store
import { create } from 'zustand'
// 创建一个 store,返回一个自定义 Hook:useCounterStore
const useCounterStore = create((set) => ({
// 状态:count,初始值为 0
count: 0,
// 修改状态的方法:增加 1
increment: () => set((state) => ({ count: state.count + 1 })),
// 修改状态的方法:减少 1
decrement: () => set((state) => ({ count: state.count - 1 })),
// 修改状态的方法:重置为 0
reset: () => set({ count: 0 }),
}))
// 导出 store,供组件使用
export default useCounterStore
说明:
create((set) => ({ ... }))
:创建一个 store。set
:是 Zustand 提供的函数,用来更新状态。state
:当前的状态对象。export default
:导出这个 store,供组件使用。
2. 在组件中使用 Store
创建组件文件 Counter.jsx
jsx
// 导入 store
import useCounterStore from '../store/useCounterStore'
// Counter 组件
const Counter = () => {
// 使用 store 中的状态和方法
const { count, increment, decrement, reset } = useCounterStore()
return (
<div>
<h2>当前计数:{count}</h2>
<button onClick={increment}>+1</button>
<button onClick={decrement}>-1</button>
<button onClick={reset}>重置</button>
</div>
)
}
export default Counter
说明:
useCounterStore()
:调用这个 Hook,获取 store 中的状态和方法。count
:从 store 中拿到当前的count
值。increment()
/decrement()
:点击按钮调用 store 中的方法,修改状态。reset()
:重置计数器为 0。
三、 进阶:管理异步请求状态
场景:请求 GitHub 用户仓库列表
1. 创建 API 请求函数
js
// src/api/github.js
export const getRepoList = async (owner) => await axios.get(`https://api.github.com/users/${owner}/repos`);
2.创建 Store
js
// src/store/repoStore.js
// 引入 zustand 和异步请求函数
import { create } from 'zustand'
import { getRepoList } from '@/api/github'
// 创建 store
const useRepoStore = create((set) => ({
repos: [], // 存储仓库数据
loading: false, // 加载状态
error: null, // 错误信息
// 异步方法:请求 GitHub 仓库数据
fetchRepos: async (username) => {
set({ loading: true, error: null }) // 开始加载
try {
const data = await getRepoList(username)
set({ repos: data, loading: false }) // 请求成功
} catch (err) {
set({ error: err.message, loading: false }) // 请求失败
}
}
}))
export default useRepoStore
说明:
repos
:存储 GitHub 仓库数据loading
:控制加载状态error
:错误信息fetchRepos
:异步方法,请求数据并更新状态
3.创建组件使用 Store
jsx
// src/components/RepoList.jsx
import useRepoStore from '../store/useRepoStore'
import { useEffect } from 'react'
const RepoList = () => {
const { repos, loading, error, fetchRepos } = useRepoStore()
useEffect(() => {
fetchRepos('saltedfish6') // 这个地方请替换为你自己的 GitHub 用户名
}, [])
if (loading) return <p>加载中...</p>
if (error) return <p>错误: {error}</p>
return (
<div>
<h2>GitHub 仓库列表</h2>
<ul>
{repos.map(repo => (
<li key={repo.id}>
<a href={repo.html_url} target="_blank" rel="noreferrer">
{repo.name}
</a>
</li>
))}
</ul>
</div>
)
}
export default RepoList
运行效果:
- 页面显示 GitHub 仓库列表
- 支持加载状态和错误处理
四、模块化 Store 设计(中大型项目推荐)
推荐的目录结构
css
src/
├── store/
│ ├── useCounterStore.js
│ └── useRepoStore.js
├── components/
│ ├── Counter.jsx
│ └── RepoList.jsx
├── App.jsx
- 每个 store 管理一个模块的状态
- 组件只导入自己需要的 store
- 项目结构清晰,便于维护
五、 Zustand 的调试与持久化
安装中间件:
bash
pnpm install @zustand/devtools-middleware
pnpm install @zustand/persist-middleware
1.使用 DevTools
js
import { devtools } from 'zustand/middleware'
const useCounterStore = create(devtools((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
reset: () => set({ count: 0 }),
})))
效果:可以在浏览器 Redux DevTools 中看到状态变化过程。
2.使用持久化
js
import { persist } from 'zustand/middleware'
const useCounterStore = create(persist((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}), {
name: 'count-storage'
}))
效果:页面刷新后,状态不会丢失。