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'
}))

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

相关推荐
fs哆哆13 分钟前
在VB.net中,函数:列数字转字母
java·服务器·前端·javascript·.net
挽淚41 分钟前
Framer Motion:React动画开发
react.js
Hilaku1 小时前
别再手写i18n了!深入浏览器原生Intl对象(数字、日期、复数处理)
前端·javascript·代码规范
每天吃饭的羊1 小时前
强制缓存与协商缓存
前端
挽淚1 小时前
前端认证入门:基于JWT的身份认证演示项目
react.js
缘来小哥1 小时前
Nodejs的多版本管理,不仅仅只是nvm的使用
前端·node.js
陈随易1 小时前
Vite和pnpm都在用的tinyglobby文件匹配库
前端·后端·程序员
LeeAt1 小时前
还在为移动端项目组件发愁?快来试试React Vant吧!
前端·web components
鹏程十八少1 小时前
4. Android 用户狂赞的UI特效!揭秘折叠卡片+流光动画的终极实现方案
前端
Cache技术分享2 小时前
141. Java 泛型 - Java 泛型方法的类型擦除
前端·后端