5月28日 00:45

什么是 Zustand,它与其他状态管理库相比有哪些优势?

核心答案

Zustand 是一个极简的 React 状态管理库,gzip 后仅约 1KB。它通过 create 函数创建 store,组件用 hook 订阅状态,无需 Provider 包裹,也不需要 reducer/action 等样板代码。与 Redux 相比,Zustand 的 API 更简洁、包体积小 5-7 倍、重渲染速度快 30-50%,已成为 2026 年新 React 项目的首选状态管理方案。

基本用法

创建一个 store 只需要调用 create

js
import { create } from 'zustand' const useStore = create((set) => ({ count: 0, increment: () => set((state) => ({ count: state.count + 1 })), decrement: () => set((state) => ({ count: state.count - 1 })), }))

组件中使用:

jsx
function Counter() { const { count, increment, decrement } = useStore() return ( <div> <span>{count}</span> <button onClick={increment}>+1</button> <button onClick={decrement}>-1</button> </div> ) }

没有任何 Provider、没有 action 类型定义、没有 switch-case reducer。状态更新直接通过 set 函数完成。

选择性订阅:减少不必要的重渲染

这是 Zustand 的关键优势之一。组件可以只订阅它关心的状态切片:

jsx
// 只在 count 变化时重渲染,其他状态更新不会触发 const count = useStore((state) => state.count) // 也可以用 selector 订阅派生状态 const isPositive = useStore((state) => state.count > 0)

相比之下,React Context 的消费者在 context 值变化时会全部重渲染,这在大型应用中是性能瓶颈。

与其他状态管理库的对比

特性ZustandRedux ToolkitJotaiValtio
包体积 (gzip)~1KB~6-8KB~3KB~3KB
状态模型不可变不可变原子化可变
需要 Provider
样板代码量极少中等极少极少
学习曲线平缓中等平缓平缓
DevTools 支持内置完整基础基础
TypeScript 支持优秀优秀优秀良好

选择建议:中小型项目、追求简单高效选 Zustand;大型团队需要严格架构和可预测数据流选 Redux Toolkit;需要细粒度原子状态选 Jotai;偏好可变状态写法选 Valtio。

中间件:持久化与开发调试

Zustand 的中间件机制让功能扩展非常方便:

js
import { create } from 'zustand' import { persist, devtools } from 'zustand/middleware' const useStore = create( devtools( persist( (set) => ({ theme: 'light', toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light', })), }), { name: 'theme-storage' } ), { name: 'ThemeStore' } ) )

persist 将状态自动同步到 localStorage,页面刷新后状态不丢失。devtools 集成 Redux DevTools 扩展,方便调试状态变化。中间件可以自由组合,按需叠加。

在 Next.js 中使用

Zustand 与 Next.js App Router 配合时,需要注意 store 不能在模块顶层直接创建(服务端会共享状态),推荐使用懒初始化模式:

jsx
// store.js import { create } from 'zustand' const useStore = create((set) => ({ user: null, setUser: (user) => set({ user }), })) export default useStore // layout.jsx 或 page.jsx 'use client' import useStore from './store' export default function Page() { const user = useStore((state) => state.user) return <div>{user?.name ?? '未登录'}</div> }

关键点是将使用 store 的组件标记为 'use client',store 本身保持普通的模块导出即可。

异步操作

Zustand 处理异步不需要额外的中间件(Redux 需要 redux-thunk 或 createAsyncThunk),直接在 set 中写 async 函数:

js
const useStore = create((set) => ({ data: null, loading: false, error: null, fetchData: async (id) => { set({ loading: true, error: null }) try { const res = await fetch(`/api/data/${id}`) const data = await res.json() set({ data, loading: false }) } catch (error) { set({ error: error.message, loading: false }) } }, }))

追问:什么时候不该用 Zustand?

如果项目只需要组件间传递少量状态,React 自带的 useState + useContext 就够了,没必要引入外部库。另外,服务端状态(API 请求缓存、分页数据)更适合用 TanStack Query 管理,Zustand 专注的是客户端 UI 状态。两者经常在同一项目中配合使用——TanStack Query 管接口数据,Zustand 管界面交互状态。

标签:Zustand