一个比RTK或redux更轻量级更易使用的 React 第三方状态管理工具库的配置与使用
本文由作者 Samdy_Chan 原创,未经作者同意,请勿随意转载!
使用轻量级第三方的 React 状态管理库 zustand 管理共享状态数据
在 react 框架应用中,开发者应该大多数都是采用 redux 状态管理工具库来管理应用的共享状态数据,但用过 redux 的人都知道,其配置和使用相当复杂繁琐,先要定义对应操作状态数据方法的 action,然后创建 reducer 函数,在函数内要分别根据不同 action 对状态数据做不同的操作,还要根据 reducer 创建 store 对象,如果对于异步操作的 action,还需要安装第三方支持异步 action 的中间件库 redux-thunk,使用和配置起来非常麻烦。
虽然后来出现了精简版的 redux 状态管理库:@reduxjs/toolkit(RTK),对其之前使用原始 redux 库的配置和操作进行了精简处理,而且不用再自己手动安装用于支持异步 action 的 redux-thunk 库,安装时,其会自动安装 redux-thunk 库。也无须开发者自己手动配置和注册 redux-thunk,其使用步骤精简了不少。但一般来说,对于异步 action 函数还是需要和同步 action 进行分别定义,然后在异步 action 里再调用同步 action。
所以现在,给大家推荐一个更加轻量级的,速度更快的,配置简单,对 TS 类型支持友好的另一个第三方状态数据管理工具库 zustand,目前最新版本为 5.0.2,是一个塞尔维亚人开发。zustand 库目前周下载量达到300多400万次,基本与 redux 库下载量持平
zustand 该状态管理库的主要优点如下:
- 将状态变量(当前也是自带响应式的),及操作状态变量的 action 函数在同一个返回对象中定义;
- 对于异步 action 函数,没有任何区别,也是在一起定义即可,无须像redux 那样分别定义;
- 在定义状态变量的 action 函数的同一个返回对象中,可以同时定义多个状态变量,以及对应多个操作状态变量的 action 函数;
- 也可以分模块,将不同模块或功能的状态变量及其对应的 action 函数定义在不同的 store 文件中,再通过组合导出;
- zustand 同时也支持通过调用 zustand/middleware 中间件函数 devtools(),将操作状态数据的过程和结果在浏览器的调试工具栏(F12)中的 redux devtools 插件面板中显示出来,前提是要先安装有 redux devtools 该浏览器插件,如下图所示:
即使没有安装该插件,也不影响使用;
zustand 的安装配置及使用说明
一、安装 zustand
# yarn 推荐用 yarn,就因为 react 和 yarn 都是 Facebook Meta 公司开发的,哈哈^_^
yarn add zustand
# npm
npm i zustand
# pnpm
pnpm add zustand
二、配置和使用 zustand store:分模块配置
-
2.1、本案例创建两个 store 模块文件,分别为实现年龄计数器状态数据和对应操作增减年龄状态数据 action 方法的 store;及通过异步 action 获取频道列表数据保存到 channelList 状态变量的 store。分别定义在 src/store/counterStore.ts 及 src/store/channelStore.ts 文件中,这两个 store 的定义脚本内容如下:
-
2.1.1、<src/store/counterStore.ts>
// src/store/counterStore.ts
// 导入 zustand 状态管理库创建 store 的方法 create
import {
create } from 'zustand';
// 定义counterStore(包括状态变量和操作方法)的数据类型
export type CounterStoreType = {
count: number;
incrCount: Function;
decrCount: (val?: number) => void;
asyncIncrCount: () => Promise<void>;
};
// 创建并导出 counter 模块的 store 对象
export const useCounterStore = create<CounterStoreType>((set, get) => {
// zustand.create 方法的回调函数需要返回一个包含初始化状态数据和操作状态数据方法的对象
return {
// 初始化状态数据
count: 0,
// 增加状态数据的方法
incrCount: () => {
// 如果需要引用原本 state 状态 count 的值,set 函数里需要传入 state
set((state) => ({
count: state.count + 1 }));