Redux的使用
到如今redux的已经不是react程序中必须的一部分内容了,
我们应该在本地需要大量更新全局变量时才使用它!
redux vs reducer
reducer的工作机制:
手动构造action对象传入dispatch函数中
dispatch函数将 action传入reducer当中
reducer结合当前state与action生成新的state
重新渲染
redux的工作机制:
其中store中有多个reducer
单独编写生成action的函数,集中管理action
传统实现案例
import { createStore } from "redux";const initialState = {balance: 0,loan: 0,loanPurpose: "",
};function reducer(state = initialState, action) {switch (action.type) {case "account/deposit":return {...state,balance: state.balance + action.payload,};case "account/withdraw":return {...state,balance: state.balance - action.payload,};case "account/requestLoan":if (state.loan > 0) return state;return {...state,loan: action.payload.amount,loanPurpose: action.payload.loanPurpose,balance: state.balance + action.payload.amount,};case "account/payLoan":return {...state,loan: 0,loanPurpose: "",balance: state.balance - state.loan,};default:return state;}
}const store = createStore(reducer);store.dispatch({ type: "account/deposit", payload: 500 });console.log(store.getState());
这与reducer的实现非常相似
我们不能一直手写类型,这非常不方便。所以要有相关函数来做这部分内容。
import { createStore } from "redux";const initialState = {balance: 0,loan: 0,loanPurpose: "",
};function reducer(state = initialState, action) {switch (action.type) {case "account/deposit":return {...state,balance: state.balance + action.payload,};case "account/withdraw":return {...state,balance: state.balance - action.payload,};case "account/requestLoan":if (state.loan > 0) return state;return {...state,loan: action.payload.amount,loanPurpose: action.payload.loanPurpose,balance: state.balance + action.payload.amount,};case "account/payLoan":return {...state,loan: 0,loanPurpose: "",balance: state.balance - state.loan,};default:return state;}
}const store = createStore(reducer);function deposit(payload) {return { type: "account/deposit", payload: payload };
}function withdraw(payload) {return { type: "account/withdraw", payload: payload };
}function requestLoan(payload) {return { type: "account/requestLoan", payload: payload };
}function payLoan(payload) {return { type: "account/payLoan" };
}store.dispatch(deposit(500));
store.dispatch(withdraw(200));
store.dispatch(requestLoan({ amount: 1000, loanPurpose: "Buy a car" }));
store.dispatch(payLoan());
redux中一般store中有多个reducer,我们可以组织代码如下:
accountSlice文件中放置account相关的state:
const initialState = {balance: 0,loan: 0,loanPurpose: "",
};export default function accountReducer(state = initialState, action) {switch (action.type) {case "account/deposit":return {...state,balance: state.balance + action.payload,};case "account/withdraw":return {...state,balance: state.balance - action.payload,};case "account/requestLoan":if (state.loan > 0) return state;return {...state,loan: action.payload.amount,loanPurpose: action.payload.loanPurpose,balance: state.balance + action.payload.amount,};case "account/payLoan":return {...state,loan: 0,loanPurpose: "",balance: state.balance - state.loan,};default:return state;}
}export function deposit(amount) {return { type: "account/deposit", payload: amount };
}export function withdraw(amount) {return { type: "account/withdraw", payload: amount };
}export function requestLoan(payload) {return { type: "account/requestLoan", payload: payload };
}export function payLoan() {return { type: "account/payLoan" };
}
customerSlice文件中放置customer相关的state:
const initialCustormerState = {fullName: "",nationalID: "",createdAt: "",
};export default function customerReducer(state = initialCustormerState, action) {switch (action.type) {case "customer/createCustomer":return {...state,fullName: action.payLoad.fullName,nationalID: action.payLoad.nationalID,createdAt: action.payLoad.createdAt,};case "customer/updateName":return {...state,fullName: action.payLoad.fullName,};default:return state;}
}export function createCustomer(fullName, nationalID) {return {type: "customer/createCustomer",payLoad: {fullName: fullName,nationalID: nationalID,createdAt: new Date().toISOString(),},};
}export function updateName(fullName) {return {type: "account/updateName",payLoad: fullName,};
}
store文件中对reducer进行组合:
import { createStore, combineReducers } from "redux";
import customerReducer from "./features/customer/customerSlice";
import accountReducer from "./features/account/accountSlice";const rootReducer = combineReducers({customer: customerReducer,account: accountReducer,
});const store = createStore(rootReducer);export default store;
导入index.js中即可:
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import store from "./store";const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<React.StrictMode><App /></React.StrictMode>
);
然后将redux与react联系起来,这与contextAPI非常相似,提供一个Provider,并且传入store:
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store";const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>
);
然后各个组件中就可以通过useSelector hook获取store中的state,通过useDispatch hook就可以获取dispatch传递action
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { deposit, payLoan, requestLoan, withdraw } from "./accountSlice";function AccountOperations() {const [depositAmount, setDepositAmount] = useState("");const [withdrawalAmount, setWithdrawalAmount] = useState("");const [loanAmount, setLoanAmount] = useState("");const [loanPurpose, setLoanPurpose] = useState("");const [currency, setCurrency] = useState("USD");const { loan: currentLoan, loanPurpose: currencyLoanPurpose } = useSelector((store) => store.account);const dispatch = useDispatch();function handleDeposit() {if (!depositAmount) return;dispatch(deposit(depositAmount));setDepositAmount("");}function handleWithdrawal() {if (!withdrawalAmount) return;dispatch(withdraw(withdrawalAmount));setWithdrawalAmount("");}function handleRequestLoan() {if (!loanAmount || !loanPurpose) return;dispatch(requestLoan(loanAmount, loanPurpose));setLoanAmount("");setLoanPurpose("");}function handlePayLoan() {dispatch(payLoan());}return (<div><h2>Your account operations</h2><div className="inputs"><div><label>Deposit</label><inputtype="number"value={depositAmount}onChange={(e) => setDepositAmount(+e.target.value)}/><selectvalue={currency}onChange={(e) => setCurrency(e.target.value)}><option value="USD">US Dollar</option><option value="EUR">Euro</option><option value="GBP">British Pound</option></select><button onClick={handleDeposit}>Deposit {depositAmount}</button></div><div><label>Withdraw</label><inputtype="number"value={withdrawalAmount}onChange={(e) => setWithdrawalAmount(+e.target.value)}/><button onClick={handleWithdrawal}>Withdraw {withdrawalAmount}</button></div><div><label>Request loan</label><inputtype="number"value={loanAmount}onChange={(e) => setLoanAmount(+e.target.value)}placeholder="Loan amount"/><inputvalue={loanPurpose}onChange={(e) => setLoanPurpose(e.target.value)}placeholder="Loan purpose"/><button onClick={handleRequestLoan}>Request loan</button></div>{currentLoan > 0 && (<div><span>Pay back {currentLoan} {currencyLoanPurpose}</span><button onClick={handlePayLoan}>Pay loan</button></div>)}</div></div>);
}export default AccountOperations;
middleware 与 redux chunk
由于store本身的局限性无法处理异步情况,所以在dispatch传递时,不直接到reducer中,而是先通过middle ware。而redux chunk就是reudx目前最流行的middle ware第三方库。
首先在store中进行middle ware的配置:
import { createStore, combineReducers, applyMiddleware } from "redux";
import { thunk } from "redux-thunk";
import customerReducer from "./features/customer/customerSlice";
import accountReducer from "./features/account/accountSlice";const rootReducer = combineReducers({customer: customerReducer,account: accountReducer,
});const store = createStore(rootReducer, applyMiddleware(thunk));export default store;
然后在action中进行异步情况的处理:
export function deposit(amount, currency) {if (currency === "USD") return { type: "account/deposit", payload: amount };return async function (dispatch, getState) {dispatch({ type: "account/convertingCurrency" });const res = await fetch(`https://api.frankfurter.app/latest?amount=${amount}&from=${currency}&to=USD`);const data = await res.json();console.log(data);const converted_deposit = data.rates.USD;dispatch({ type: "account/deposit", payload: converted_deposit });};
}
当我们返回的不是一个对象,而是一个函数时,redux就会意识到这个函数是一个“thunk”,redux就不会马上将其传递到store的reducer中,而是会运行这个函数“thunk”,并将dispatch和getState作为函数参数传递到函数“thunk”中。
相关文章:

Redux的使用
到如今redux的已经不是react程序中必须的一部分内容了, 我们应该在本地需要大量更新全局变量时才使用它! redux vs reducer reducer的工作机制: 手动构造action对象传入dispatch函数中 dispatch函数将 action传入reducer当中 reducer结合当前state与a…...
【JAVA】Java高级:多数据源管理与Sharding:数据分片(Sharding)技术的实现与实践
大规模分布式系统,数据存储和管理变得越来越复杂。随着用户数量和数据量的急剧增加,单一数据库往往难以承载如此庞大的负载。这时,数据分片(Sharding)技术应运而生。数据分片是一种将数据水平切分到多个数据库实例的技…...

ASP.NET Core 9.0 静态资产传递优化 (MapStaticAssets )
一、结论 💢先看结论吧, MapStaticAssets 在大多数情况下可以替换 UseStaticFiles,它已针对为应用在生成和发布时了解的资产提供服务进行了优化。 如果应用服务来自其他位置(如磁盘或嵌入资源)的资产,则应…...
LeetCode刷题day18——贪心
LeetCode刷题day18——贪心 135. 分发糖果分析: 406. 根据身高重建队列分析:for (auto& p : people) 昨天写了一道,今天写了一道,都有思路,却不能全整对。昨天和小伙伴聊天,说是因为最近作业多…...

MATLAB Simulink® - 智能分拣系统
系列文章目录 前言 本示例展示了如何在虚幻引擎 环境中对四种不同形状的标准 PVC 管件实施半结构化智能分拣。本示例使用 Universal Robots UR5e cobot 执行垃圾箱拣选任务,从而成功检测并分类物体。cobot 的末端执行器是一个吸力抓手,它使 cobot 能够拾…...

linuxCNC(五)HAL驱动的指令介绍
HAL驱动的构成 指令举例详解 从终端进入到HAL命令行,执行halrun,即可进入halcmd命令行 # halrun指令描述oadrt加载comoonent,loadrt threads name1 period1创建新线程loadusr halmeter加载万用表UI界面loadusr halscope加载示波器UI界面sho…...

STM32 进阶 定时器3 通用定时器 案例2:测量PWM的频率/周期
需求分析 上一个案例我们输出了PWM波,这个案例我们使用输入捕获功能,来测试PWM波的频率/周期。 把测到的结果通过串口发送到电脑,检查测试的结果。 如何测量 1、输入捕获功能主要是:测量输入通道的上升沿和下降沿 2、让第一个…...

第一节、电路连接【51单片机-TB6600驱动器-步进电机教程】
摘要:本节介绍如何搭建一个51单片机TB6600驱动器步进电机控制电路,所用材料均为常见的模块,简单高效的方式搭建起硬件环境 一、硬件清单 ①51单片机最小控制系统 ②USB转TTL模块 ③开关电源 ④TB6600步进电机驱动器 ⑤二相四线步进电机 ⑥电…...
【通俗理解】Koopman算符与非线性动力系统分析
【通俗理解】Koopman算符与非线性动力系统分析 关键词: #Koopman算符 Koopman Operator #非线性动力系统 Nonlinear Dynamical System #无穷维线性算子 Infinite-Dimensional Linear Operator #演化分析 Evolution Analysis #Bernard Koopman Bernard Koopman 第…...
mybatis plus打印sql日志
1、官方文档 使用配置 | MyBatis-Plus 2、日志实现 MyBatis-Plus 提供了多种日志实现(log-impl),用于记录 SQL 语句和相关操作,帮助开发者进行调试和监控数据库操作。以下是一些可用的日志实现及其说明: StdOutImpl…...
ObjectMapper
ObjectMapper 是 Jackson 库中非常重要的一个类,它是 JSON 和 Java 对象之间进行序列化与反序列化的核心工具。ObjectMapper 的底层实现是基于 Jackson 的数据绑定模型,它将 Java 对象与 JSON 数据转换为互通格式。 1. ObjectMapper 的设计与核心功能 O…...
新增白名单赋予应用安装权限
目录 相关问题 具体实现 相关问题 安装app到/data/分区时,如何在安装阶段就赋予权限,无需请求权限 具体实现 frameworks/base/core/res/res/values/config.xml <!-- For whitelis apk --><string-array translatable"false" nam…...
传奇996_51——脱下装备,附加属性设为0
奶奶的lua怎么都修改不了,可以调用txt的 ; LINKPICKUPITEM ; ChangeitemaddvaLue -1 5 0 ; GETITEMADDVALUE 3 5 M10 ; SENDUPGRADEITEM ; SENDMSG 9 你的衣服附加了<$STR(M10)>点防御属性. 或者lua callscriptex(actor,“LINKPICKUPITEM”) callscriptex(…...

【Mac】安装Gradle
1、说明 Gradle 运行依赖 JVM,需要先安装JDK,Gradle 与 JDK的版本对应参见:Java Compatibility IDEA的版本也是有要求Gradle版本的,二者版本对应关系参见:Third-Party Software and Licenses 本次 Gradle 安装版本为…...
MySQL中的redoLog
在数据库系统中,redo log(重做日志)用于记录所有已提交事务的修改操作,它的主要目的是确保在系统崩溃或故障后,能够恢复数据库到崩溃前的状态。Redo log 记录的是事务修改的数据的具体操作,而不是数据本身。…...

Windows 安装 MySQL
1.下载 MySQL 安装包 访问:MySQL :: Download MySQL Installer选择适合的版本。推荐下载 MySQL Installer for Windows,该安装包包含所有必要的组件选择 Windows (x86, 32-bit), MSI Installer 或 Windows (x86, 64-bit), MSI Installer 2.运行安装程序…...
yocto的xxx.bb文件在什么时候会拷贝文件到build目录
在 Yocto 中,.bb 文件用于描述如何构建和安装一个软件包,而文件在构建过程中的拷贝操作通常会在某些特定的步骤中进行。具体来说,文件会在以下几个阶段被拷贝到 build 目录(或者更准确地说,拷贝到目标目录 ${D}&#x…...

Ubuntu Server 22.04.5 LTS重启后IP被重置问题
Ubuntu Server 22.04.5 LTS重启后IP被重置问题 最近在使用Ubuntu Server 22.04做项目开发测试时发现每次重启和关机后,所设置的静态IP地址都会回复到安装系统时所设置的ip Ubuntu Server 22.04 官网下载地址:Ubuntu官方下载地址 对虚拟机下安装Ubuntu感…...

Java基础复习
“任何时候我也不会满足,越是多读书,就越是深刻地感到不满足,越感到自己知识贫乏。科学是奥妙无穷的。” ——马克思 目录 一、方法&方法重载 二、运算符 三、数据类型 四、面向对象 1. 面向对象思想 2. 引用传递 3. 访问权限修饰…...

简易图书管理系统
javawebjspservlet 实体类 package com.ghx.entity;/*** author :guo* date :Created in 2024/12/6 10:13* description:* modified By:* version:*/ public class Book {private int id;private String name;private double pri…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
React核心概念:State是什么?如何用useState管理组件自己的数据?
系列回顾: 在上一篇《React入门第一步》中,我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目,并修改了App.jsx组件,让页面显示出我们想要的文字。但是,那个页面是“死”的,它只是静态…...