Zustand 入门:用最简单的方式管理 React 全局状态

一、 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 需要 createStorereduceraction 直接 create((set) => ({ ... }))
修改状态 需要 dispatch(action) 直接调用方法如 increment()
是否需要 Provider 是,需要包裹 <Provider> 否,直接使用 Hook
异步操作 需配合 redux-thunkredux-saga 可直接在 store 中写 async/await
状态更新方式 不可变更新(state => newState 支持不可变更新,也可以直接赋值
学习成本 较高(需要理解 action、reducer、dispatch) 极低(直接写状态和方法)
TypeScript 支持 支持,但配置较复杂 支持良好,类型推导更简单
调试工具 支持 Redux DevTools 支持 Redux DevTools(通过中间件)
体积 约 2KB(+ thunk/saga) 压缩后约 1KB

4.Zustand 的定位

  • 不是 Redux 的替代品 ,而是简化版的状态管理方案
  • 适合大多数中小型项目,尤其是不想写冗长 reduceraction 的开发者。
  • 如果你只需要共享状态、修改状态、监听状态变化,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'
}))

效果:页面刷新后,状态不会丢失。

相关推荐
2501_920931706 小时前
React Native鸿蒙跨平台采用ScrollView的horizontal属性实现横向滚动实现特色游戏轮播和分类导航
javascript·react native·react.js·游戏·ecmascript·harmonyos
0思必得08 小时前
[Web自动化] Selenium处理动态网页
前端·爬虫·python·selenium·自动化
摘星编程8 小时前
React Native鸿蒙版:Drawer抽屉导航实现
react native·react.js·harmonyos
东东5168 小时前
智能社区管理系统的设计与实现ssm+vue
前端·javascript·vue.js·毕业设计·毕设
catino8 小时前
图片、文件的预览
前端·javascript
2501_9209317010 小时前
React Native鸿蒙跨平台实现推箱子游戏,完成玩家移动与箱子推动,当所有箱子都被推到目标位置时,玩家获胜
javascript·react native·react.js·游戏·ecmascript·harmonyos
layman052810 小时前
webpack5 css-loader:从基础到原理
前端·css·webpack
半桔10 小时前
【前端小站】CSS 样式美学:从基础语法到界面精筑的实战宝典
前端·css·html
AI老李10 小时前
PostCSS完全指南:功能/配置/插件/SourceMap/AST/插件开发/自定义语法
前端·javascript·postcss
_OP_CHEN10 小时前
【前端开发之CSS】(一)初识 CSS:网页化妆术的终极指南,新手也能轻松拿捏页面美化!
前端·css·html·网页开发·样式表·界面美化