当前位置: 首页 > news >正文

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程序中必须的一部分内容了&#xff0c; 我们应该在本地需要大量更新全局变量时才使用它! redux vs reducer reducer的工作机制&#xff1a; 手动构造action对象传入dispatch函数中 dispatch函数将 action传入reducer当中 reducer结合当前state与a…...

【JAVA】Java高级:多数据源管理与Sharding:数据分片(Sharding)技术的实现与实践

大规模分布式系统&#xff0c;数据存储和管理变得越来越复杂。随着用户数量和数据量的急剧增加&#xff0c;单一数据库往往难以承载如此庞大的负载。这时&#xff0c;数据分片&#xff08;Sharding&#xff09;技术应运而生。数据分片是一种将数据水平切分到多个数据库实例的技…...

ASP.NET Core 9.0 静态资产传递优化 (MapStaticAssets )

一、结论 &#x1f4a2;先看结论吧&#xff0c; MapStaticAssets 在大多数情况下可以替换 UseStaticFiles&#xff0c;它已针对为应用在生成和发布时了解的资产提供服务进行了优化。 如果应用服务来自其他位置&#xff08;如磁盘或嵌入资源&#xff09;的资产&#xff0c;则应…...

LeetCode刷题day18——贪心

LeetCode刷题day18——贪心 135. 分发糖果分析&#xff1a; 406. 根据身高重建队列分析&#xff1a;for (auto& p : people) 昨天写了一道&#xff0c;今天写了一道&#xff0c;都有思路&#xff0c;却不能全整对。昨天和小伙伴聊天&#xff0c;说是因为最近作业多&#xf…...

MATLAB Simulink® - 智能分拣系统

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

linuxCNC(五)HAL驱动的指令介绍

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

STM32 进阶 定时器3 通用定时器 案例2:测量PWM的频率/周期

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

第一节、电路连接【51单片机-TB6600驱动器-步进电机教程】

摘要&#xff1a;本节介绍如何搭建一个51单片机TB6600驱动器步进电机控制电路&#xff0c;所用材料均为常见的模块&#xff0c;简单高效的方式搭建起硬件环境 一、硬件清单 ①51单片机最小控制系统 ②USB转TTL模块 ③开关电源 ④TB6600步进电机驱动器 ⑤二相四线步进电机 ⑥电…...

【通俗理解】Koopman算符与非线性动力系统分析

【通俗理解】Koopman算符与非线性动力系统分析 关键词&#xff1a; #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 提供了多种日志实现&#xff08;log-impl&#xff09;&#xff0c;用于记录 SQL 语句和相关操作&#xff0c;帮助开发者进行调试和监控数据库操作。以下是一些可用的日志实现及其说明&#xff1a; StdOutImpl…...

ObjectMapper

ObjectMapper 是 Jackson 库中非常重要的一个类&#xff0c;它是 JSON 和 Java 对象之间进行序列化与反序列化的核心工具。ObjectMapper 的底层实现是基于 Jackson 的数据绑定模型&#xff0c;它将 Java 对象与 JSON 数据转换为互通格式。 1. ObjectMapper 的设计与核心功能 O…...

新增白名单赋予应用安装权限

目录 相关问题 具体实现 相关问题 安装app到/data/分区时&#xff0c;如何在安装阶段就赋予权限&#xff0c;无需请求权限 具体实现 frameworks/base/core/res/res/values/config.xml <!-- For whitelis apk --><string-array translatable"false" nam…...

传奇996_51——脱下装备,附加属性设为0

奶奶的lua怎么都修改不了&#xff0c;可以调用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&#xff0c;需要先安装JDK&#xff0c;Gradle 与 JDK的版本对应参见&#xff1a;Java Compatibility IDEA的版本也是有要求Gradle版本的&#xff0c;二者版本对应关系参见&#xff1a;Third-Party Software and Licenses 本次 Gradle 安装版本为…...

MySQL中的redoLog

在数据库系统中&#xff0c;redo log&#xff08;重做日志&#xff09;用于记录所有已提交事务的修改操作&#xff0c;它的主要目的是确保在系统崩溃或故障后&#xff0c;能够恢复数据库到崩溃前的状态。Redo log 记录的是事务修改的数据的具体操作&#xff0c;而不是数据本身。…...

Windows 安装 MySQL

1.下载 MySQL 安装包 访问&#xff1a;MySQL :: Download MySQL Installer选择适合的版本。推荐下载 MySQL Installer for Windows&#xff0c;该安装包包含所有必要的组件选择 Windows (x86, 32-bit), MSI Installer 或 Windows (x86, 64-bit), MSI Installer 2.运行安装程序…...

yocto的xxx.bb文件在什么时候会拷贝文件到build目录

在 Yocto 中&#xff0c;.bb 文件用于描述如何构建和安装一个软件包&#xff0c;而文件在构建过程中的拷贝操作通常会在某些特定的步骤中进行。具体来说&#xff0c;文件会在以下几个阶段被拷贝到 build 目录&#xff08;或者更准确地说&#xff0c;拷贝到目标目录 ${D}&#x…...

Ubuntu Server 22.04.5 LTS重启后IP被重置问题

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

Java基础复习

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

简易图书管理系统

javawebjspservlet 实体类 package com.ghx.entity;/*** author &#xff1a;guo* date &#xff1a;Created in 2024/12/6 10:13* description&#xff1a;* modified By&#xff1a;* version:*/ public class Book {private int id;private String name;private double pri…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...