Redux Hooks actions 调用方式优化(一)

news2024/11/25 14:46:49

hooks 可以说是现在react编程的的主流,redux 迎合这个主流也推出 toolkit 工具集来。但是在用toolkit 搭建前端框架后,给人的感觉就是比原先的connect 那一套好些,但用起来还是挺繁琐的。

一 toolkit 搭建的正常使用版本

1.1 创建store

import { configureStore } from '@reduxjs/toolkit'

export const store = configureStore({
  reducer: {},
})

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch

通过Priovider 绑定到root组件里面

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

1.2 创建model

通过toolkit 提供的createSlice 来 创建model

import { createSlice } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
export interface CounterState {
  value: number
}
const initialState: CounterState = {
  value: 0,
}

export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
   //同步actions 
    increment: (state) => {
      state.value += 1
    },
    decrement: (state) => {
      state.value -= 1
    },
    incrementByAmount: (state, action: PayloadAction<number>) => {
      state.value += action.payload
    },
  },
})

// 分别导出actions
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer

嵌入到store 里面

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
})

1.3 在组件里面使用model 的state 和actions的方式

state 官网推荐useSelector 获取,具体代码如下:

const count = useSelector((state: RootState) => state.counter.value)

actions 官方给的例子是通过import 引入,再通过dispatch 派发

import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'

const dispatch = useDispatch();
dispatch(increment())  // 每个actions 运行都需要用dispatch 派发 
dispatch(decrement())

每个action的运行都需要用dispatch 派发, 如果一个组件使用了10多个action,dispatch 就需要重复出现10多次,明显的代码(dispatch)冗余,这让人有点难受。

二:怎么缩减dispatch出现的次数?

每个action都需要一个dispatch派出,在优化action的dispatch 前,我们先设想下什么样的api 比较理想?有方向才好改代码。
借鉴easy-peasy 库的理念,理想的情况应该是这样的:用useStoreState 获取state,用useStoreActions 获取actions,用到action是直接执行action函数。举个例子:

//组件内引入 useStoreState 、useStoreActions
const { value} = useStoreState((state) => state.counterSlice);
const { increment, decrement, incrementByAmount } = useStoreActions((actions) => actions.counterSlice);

//组件使用action
increment();
decrement();
incrementByAmount(1);

这样看,代码简洁就提升了非常多,也非常方便在组件里面引用。

三、useStoreState 、useStoreActions的具体实现

3.1 创建 生成 useStoreState 和 useStoreActions 的工厂函数

useStoreState 直接等效于useSelector Api ,这里就相关于改变了下命名。

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import { AppDispatch, RootState } from './store';

export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
function createTypedHooks() {
  return {
    useStoreState: useAppSelector,
  };
}
const typedHooks = createTypedHooks();
//export const useStoreActions = typedHooks.useStoreActions;
export const useStoreState = typedHooks.useStoreState;

useStoreActions 的实现思路:先获取对应model的action ,然后再在action 外层套上dispatch函数。

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import { AppDispatch, RootState, globalDispath} from './store';
import storeModel from '@src/models';
// storeModel.storeModelActions 这里先假设获取能获取对应的model,createStoreActionsHook函数给每个actions套上dispatch
const storeActions = createStoreActionsHook(storeModel.storeModelActions);
const typedHooks = createTypedHooks();
export const useStoreActions = typedHooks.useStoreActions;

//下面是对应的封装函数
function createTypedHooks() {
  return {
    useStoreActions: storeActions,
  };
}
//globalDispath 来自store
type StoreModelActionsType = typeof storeModel.storeModelActions;
function createStoreActionsHook<T extends StoreModelActionsType>(store: T) {
  return <Result extends T[keyof T]>(mapActions: (action: T) => Result) => {
    const storeArr = mapActions(store) as any;
    const obj = Object.keys(storeArr).reduce((prev, v) => {
      return { ...prev, [v]: (...left: any) => globalDispath(storeArr[v](...left)) };
    }, {});

    return obj as Result;
  };
}

顺着这个思路,现在就只剩下storeModel.storeModelActions 怎么获取了。重新改下models的构造,把每个model 的reducer 和actions 单独存放

import counterModelAsync from './counter.model';
const storeModelReducer = {
  counterModel: counterModelAsync.reducer,
};
const storeModelActions = { counterModel: counterModelAsync.actions };
const storeModel = { storeModelReducer, storeModelActions};
export default storeModel;

对应的store 的引用也修改下

import { configureStore } from '@reduxjs/toolkit';
import storeModel from 'src/models';

export const store = configureStore({
  reducer: { ...storeModel.storeModelReducer },
});

export const globalDispath = store.dispatch;
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;

经过这样改造,组件里面就可以实现两个api 就能解决redux store 里面state 和action的使用了。而且能经过ts的类型 。效果如下:
在这里插入图片描述
redux的异步actions 在组件里面怎么使用,是不是也可以使用同样的方式优化?这个下篇文章再讲。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/86535.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三、pcm音频转wav

前言 ffmpeg录制下来的音频为pcm格式&#xff08;内部存储着十六进制数据&#xff09;&#xff0c;但pcm格式的音频无法直接播放 本文先将pcm转换成wav格式&#xff08;提要提前了解音频知识&#xff09; 首先分析wav文件格式&#xff08;wav的本质是在pcm数据前加上文件头&a…

[附源码]Node.js计算机毕业设计电子工厂进销存管理系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

《Linux运维总结:Centos7.6使用yum安装Mysql8.0.31》

一、使用yum安装mysql服务 官方&#xff1a;下载对应的yum源 1、yum源下载 [rootlocalhost ~]# wget https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm [rootlocalhost ~]# rpm -ivh mysql80-community-release-el7-7.noarch.rpm如下图所示&#xff1a;…

vsftpd 升级3.0.2-29 和 增加账号访问

一、下载文件至/opt 百度网盘&#xff1a; 链接: https://pan.baidu.com/s/1Ad20bm5fvw8WvtaV3uHGYA 提取码: 2pa9 二、安装 2.1、切换目录 命令&#xff1a;cd /opt 2.2、授权 命令&#xff1a;chmod x centos7.6-vsftpd-upgrade.sh 2.3、安装 命令&#xff1a;./cent…

D. Lucky Chains(gcd + 线性筛)

Problem - D - Codeforces 如果一对正整数(x,y)的最大公除数等于1(gcd(x,y)1)&#xff0c;我们就把它们命名为幸运。 让我们把由(x,y)引起的链定义为一个由(x,y), (x1,y1), (x2,y2), ..., (xk,yk)组成的序列&#xff0c;对于某个整数k≥0。 如果链中的所有配对都是幸运的&…

2022-12-13 note

1、linux内核的特点 1. linux内核是完全开源的作者&#xff1a;linusgit --> 代码版本管理工具 2. linux内核源码支持多种不同的架构&#xff0c;比如arm架构&#xff0c;powerPC,mips,Risc-V,X86等 3. linux内核采用模块化的编译的思想 4. 在linux内核中只允许出现C代码或…

优秀的PM如何轻松应对公司90%以上的沟通难题

项目经理和PMO工作中最多的事情往往是沟通&#xff0c;但是你在工作中会不会遇到很多沟通难题&#xff1f;如果其他环节的人处理不好还可以理解&#xff0c;但是咱们处理不好就说不过去了&#xff0c;并且还会让人感觉不专业&#xff0c;丧失很多机会&#xff0c;甚至失去领导的…

代码随想录Day49|121.买卖股票的最佳时期、122.买卖股票的最佳时期II

文章目录121.买卖股票的最佳时期、122.买卖股票的最佳时期II121.买卖股票的最佳时期、 文章讲解&#xff1a;代码随想录 (programmercarl.com) 题目链接&#xff1a;121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给定一个数组 prices…

Metal每日分享,调整灰度系数gamma滤镜效果

本案例的目的是理解如何用Metal实现灰度系数效果滤镜&#xff0c;输入像素rgb进行次方运算获取到新的rgb&#xff1b; Demo HarbethDemo地址 实操代码 // 灰度系数滤镜 let filter C7Gamma.init(gamma: 3.0)// 方案1: ImageView.image try? BoxxIO(element: originImage,…

[附源码]Node.js计算机毕业设计儿童闲置物品交易网站Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

六、JavaScript——变量的内存结构

一、内存 定义&#xff1a;内存是用于存储数据的地方&#xff0c;程序要执行一段代码&#xff0c;要先从硬盘加载到内存当中&#xff0c;再由内存发送给CPU,CUP才能对代码进行执行。 注&#xff1a;变量并不存储任何值&#xff0c;而是存储值的内存地址 JS定义一个变量 <s…

Telerik模拟生成规则的新设置

Telerik模拟生成规则的新设置 添加了对Microsoft.NET 7官方版本的支持。 添加了控制模拟生成规则的设置。 Telerik JustLock是一个易于使用的模拟工具&#xff0c;它将帮助您以前所未有的速度、更高的质量编写单元测试。JustLock允许您轻松地将测试场景与难以配置的依赖关系(如…

5G现场网的数字孪生体系架构

现场网面向钢铁生产和统一管理的场景&#xff0c;实现现场设备与数据采集器和控制器的网络连接和数据互通&#xff0c;现场网的ZigBee、蓝牙等短距离技术以及窄带物联网&#xff08; narrowbandinternetofthings,NB-IoT&#xff09;、超远距离&#xff08;longrange,LoRa&#…

病历开发SDK:TX Text Control ActiveX 31.x Crack

Visual Basic 6 应用程序的文档处功能齐全的文档编辑器 TX Text Control ActiveX是一种完全可编程的 Rich Edit 控件&#xff0c;它在专为 Visual Studio 设计的可重用组件中为开发人员提供了广泛的文字处理功能。它提供全面的文本格式、强大的邮件合并功能和所有文字处理关键概…

算法训练四十八天 | LeetCode 198、213、337打家劫舍专题

LeetCode 198 打家劫舍 题目简析&#xff1a; 不能偷相邻的屋子&#xff0c;求能偷到的最大金额 思路分析&#xff1a; //由于是相邻的才偷&#xff0c;因此&#xff0c;我们对于最基础的三间 //dp[3] 应该是 Math.max(dp[2],dp[1]nums[3]) //如果第一间加偷第三间的价值大…

pytest + yaml 框架 -10.allure 生成报告

前言 本插件是基于pytest框架开发的&#xff0c;所以pytest 的插件都能使用&#xff0c;生成报告可以用到 allure 报告 pip 安装插件 pip install pytest-yaml-yoyoallure 报告功能在 v1.0.8 版本上实现 allure 命令行工具 allure 是一个命令行工具&#xff0c;需要去githu…

大话设计模式之设计原则

设计原则 参考链接&#xff1a;https://datawhalechina.github.io/sweetalk-design-pattern/#/content/design_principles/dependence_inversion_principle 主要介绍以下五个设计原则&#xff1a; 1、单一职责原则 顾名思义&#xff0c;一个类只有一个职责&#xff0c;只会…

React 16.8+生命周期(新)

React16之后有三个生命周期被废弃&#xff1a; componentWillMountcomponentWillReceivePropscomponentWillUpdate React 16.8的生命周期分为三个阶段&#xff0c;分别是挂载阶段、更新阶段、卸载阶段。 挂载阶段&#xff1a; constructor&#xff1a;构造函数&#xff0c;最…

【元胞自动机】基于元胞自动机模拟考虑心理策略的人员疏散附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

2022-12-13 工作记录--Vue/JS-音乐的播放与关闭

Vue/JS-音乐的播放与关闭 一、音频资源 音频资源的位置如下&#xff1a;&#x1f447;&#x1f3fb; 二、代码 App.vue 注意点&#xff1a; 1、若切换了音频资源&#xff0c;则需要在 播放音乐前 重新加载资源——见代码里的 myAuto?.load()&#xff1b;2、若切换了页面&…