zustand --一款轻量级别的状态管理工具

redux的全局状态工具使用时候觉得有点太过繁琐,发现有zustand 一款类似pinia的状态管理工具

1. Zustand 简介

Zustand 是由 Poimandres 团队开发的状态管理库。它的主要特点包括:

  • 极简 API:几乎不需要配置或样板代码。
  • 与 React 并发模式兼容:Zustand 可以与 React 18 的并发特性兼容。
  • 灵活性:你可以轻松创建局部或全局的状态,并且支持异步状态和中间件。
  • 性能优化:内置了性能优化的工具,不会像 Redux 那样有多余的状态订阅,也不需要全局挂载,随取随用

[官网] (https://awesomedevin.github.io/zustand-vue/)

相比于 Redux 和 Redux Toolkit 这样的库,Zustand 的确具有更轻量、灵活的状态管理方式,不需要像 Redux 那样将所有状态集中到一个全局的 reducer 中统一管理。Zustand 允许你自由地在组件中导入和使用独立的 store,避免了繁琐的配置和状态耦合问题(redux 还需要全局挂载文件树)。这种自由的方式在许多场景中更加便捷。

为什么 Zustand 更灵活?

  1. 无需单一的全局状态树:Redux 强调集中化的全局状态树,所有的状态变更都需要通过 reducer 和 action 来管理,导致在大型项目中 reducer 代码可能会变得复杂臃肿。而 Zustand 则允许你为每个功能模块创建独立的 store,按需导入,减少了状态树的复杂性。
  2. 没有模板化的代码:Redux 的使用通常涉及大量模板化的代码,比如 actionsreducersdispatchthunks 等,尤其是当应用变得复杂时,管理这些逻辑会显得冗长。而 Zustand 的 API 非常简单,通过一个 create 函数就能直接创建 store,代码简洁明了。
  3. 按需使用:在 Zustand 中,每个组件只会重新渲染与它相关的状态部分。而在 Redux 中,虽然有 connectuseSelector 等优化手段,但由于状态集中在全局 store 中,状态管理往往会造成性能负担。
  4. 无需配置中间件:在 Redux 中,常常需要引入中间件(如 redux-thunkredux-saga)来处理异步操作或扩展功能。Zustand 则内置了对异步处理和其他高级功能的支持,不需要复杂的中间件配置即可使用诸如 persistdevtools 等功能。

简单对比 Zustand 和 Redux:

特性ZustandRedux
状态管理结构多个独立 store,自由组合单一全局状态树,需要 combineReducers
初始配置几乎零配置,直接使用需要初始化 store、reducers、actions 等
使用方式自由按需导入全局使用,必须通过 useSelector 等访问
异步处理直接在 store 中使用 async/await需要引入中间件,如 redux-thunkredux-saga
性能优化内置选择器,组件只更新相关状态需要手动优化 useSelectorconnect
开发工具支持支持 zustand-devtoolsRedux DevTools
模板化代码无需 actions 和 reducers,逻辑更简单必须定义 actions、reducers 和 dispatch

适用场景的比较

  • Zustand 非常适合中小型应用或项目中的独立模块。它的灵活性和简单的 API 让它适用于不需要过于复杂的状态管理场景,甚至在大型项目中,也可以利用其模块化特性按需管理状态。
  • Redux 则更适合那些需要复杂的状态管理方案,特别是在涉及到跨多个组件、多个模块间的数据流共享时,它的集中化状态管理和严格的约束有助于维护一致性。

2. 安装 Zustand

Zustand 的安装非常简单。你只需在现有的 React 项目中通过 npm 或 yarn 安装即可:

# 使用 npm 安装
npm install zustand

# 使用 yarn 安装
yarn add zustand

3. 基础用法

3.1 创建 Store

Zustand 中的 store 是通过 create 函数创建的。每个 store 都包含状态和处理状态的函数,类似于 Redux 中的 reducer 和 action。

创建一个简单的计数器 store:

// src/store/useCounterStore.js
import { create } from 'zustand';

// 创建 Zustand store
const useCounterStore = create((set) => ({
  count: 0, // 初始状态
  increase: () => set((state) => ({ count: state.count + 1 })), // 增加 count
  decrease: () => set((state) => ({ count: state.count - 1 })), // 减少 count
}));

export default useCounterStore;

在这个 store 中:

  • count: 是我们要管理的状态,初始值为 0。
  • increasedecrease: 是两个函数,分别用来增加或减少 count 的值。set 函数用于更新状态。
3.2 在组件中使用

现在,我们可以在 React 组件中使用刚刚创建的 store。你可以通过 useCounterStore 钩子来获取状态和操作函数。

// src/components/Counter.js
import React from 'react';
import useCounterStore from '../store/useCounterStore';

const Counter = () => {
  // 从 Zustand 中提取状态和操作
  const { count, increase, decrease } = useCounterStore();

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h1>{count}</h1>
      <button onClick={increase} style={{ marginRight: '10px' }}>Increase</button>
      <button onClick={decrease}>Decrease</button>
    </div>
  );
};

export default Counter;

这样我们就完成了一个简单的计数器应用。在页面上你可以点击按钮来增加或减少计数器的值。这样就可以按需导入

3.3 状态持久化和本地存储

有时候,你可能希望状态在页面刷新后依然存在。这时你可以使用 Zustand 提供的 persist 中间件将状态保存到本地存储。

// src/store/useCounterStore.js
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

const useCounterStore = create(
  persist(
    (set) => ({
      count: 0,
      increase: () => set((state) => ({ count: state.count + 1 })),
      decrease: () => set((state) => ({ count: state.count - 1 })),
    }),
    {
      name: 'counter-storage', // 本地存储的键
    }
  )
);

export default useCounterStore;

这样状态会被存储在浏览器的 localStorage 中,页面刷新后状态依然存在。


4. 高级用法

4.1 使用中间件

Zustand 支持中间件,例如持久化、日志记录或调试工具。除了 persist,你还可以使用其他中间件,比如 devtools 来与 Redux DevTools 一起工作。

安装 zustand 的 devtools 中间件:

npm install zustand-middleware

使用 devtools 中间件:

import { create } from 'zustand';
import { devtools } from 'zustand/middleware';

const useCounterStore = create(
  devtools((set) => ({
    count: 0,
    increase: () => set((state) => ({ count: state.count + 1 })),
    decrease: () => set((state) => ({ count: state.count - 1 })),
  }))
);

现在,你可以在 Redux DevTools 中监控 Zustand 的状态变化。

4.2 异步状态管理

在实际项目中,你可能会需要处理异步操作,比如从 API 获取数据。Zustand 可以轻松处理异步状态。

// src/store/useUserStore.js
import { create } from 'zustand';

const useUserStore = create((set) => ({
  users: [],
  fetchUsers: async () => {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    const data = await response.json();
    set({ users: data });
  },
}));

export default useUserStore;

在组件中使用异步状态:

// src/components/UserList.js
import React, { useEffect } from 'react';
import useUserStore from '../store/useUserStore';

const UserList = () => {
  const { users, fetchUsers } = useUserStore();

  useEffect(() => {
    fetchUsers(); // 组件挂载时获取用户数据
  }, [fetchUsers]);

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

export default UserList;
4.3 状态选择器

Zustand 支持使用状态选择器来选择状态的某一部分,避免不必要的组件重新渲染。

// 选择 count 状态而不是整个 store
const count = useCounterStore((state) => state.count);

这样只有 count 发生变化时,组件才会重新渲染。

4.4 Zustand 中的 Immer

Zustand 内部集成了 Immer.js,让你能够直接修改状态,而不需要担心状态的不可变性。

const useStore = create((set) => ({
  items: [],
  addItem: (item) =>
    set((state) => {
      state.items.push(item);
    }),
}));

5. React 18 可以使用的的新特新

Zustand 完全兼容 React 18,并且它的并发特性不会影响 Zustand 的性能。Zustand 通过非常轻量的状态订阅机制,天然支持 React 18 中的并发模式。

React 18 中的自动批处理(Automatic Batching)和并发渲染(Concurrent Rendering)对 Zustand 状态更新同样适用,因此你可以在 React 18 项目中无缝使用 Zustand。


6. 常见问题和最佳实践

6.1 Zustand 与 Redux 的区别
  • Zustand 更轻量:相比于 Redux 的样板代码和复杂配置,Zustand 更简洁。
  • 无需 reducer 和 action:Zustand 直接使用 setter 和 getter,而无需引入 reducer 和 action。
  • 更灵活:Zustand 适用于小型和中型项目,对于大型项目 Redux 可能会有更好的生态支持(如中间件、工具链)。
6.2 状态选择器与性能优化

使用状态选择器可以避免不必要的组件渲染,这是优化 Zustand 性能的重要方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝胖子不是胖子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值