React(react18)中组件通信04——redux入门
React(react18)中组件通信04——redux入门
- 1. 前言
- 1.1 React中组件通信的其他方式
- 1.2 介绍redux
- 1.2.1 参考官网
- 1.2.2 redux原理图
- 1.2.3 redux基础介绍
- 1.2.3.1 action
- 1.2.3.2 store
- 1.2.3.3 reducer
- 1.3 安装redux
- 2. redux入门例子
- 3. redux入门例子——优化1(reducer 和 store拆开)
- 3.1 想要实现的效果
- 3.2 代码设计
- 3.3 添加 重新渲染
- 3.4 附代码
- 4. redux入门例子——优化2(拆出action)
- 4.1 关于action的其他说明
- 4.2 优化——拆出action
- 4.3 优化——动态加减数字
- 4.3.1 优化看效果
- 4.3.2 附代码
1. 前言
1.1 React中组件通信的其他方式
- React(react18)中组件通信01——props.
- React(react18)中组件通信02——消息订阅与发布、取消订阅以及卸载组件时取消订阅.
- React(react18)中组件通信03——简单使用 Context 深层传递参数.
1.2 介绍redux
1.2.1 参考官网
- 讲解、例子,参考官网,官网地址如下:
Redux 中文文档——https://www.redux.org.cn/.
1.2.2 redux原理图
- 原理图,如下:

- 简单解释
- 要想更新 state 中的数据,你需要发起一个 action。
Action就是一个普通 JavaScript 对象(注意到没,这儿没有任何魔法?)用来描述发生了什么。 - 强制使用 action 来描述所有变化带来的好处是可以清晰地知道应用中到底发生了什么。如果一些东西改变了,就可以知道为什么变。action 就像是描述发生了什么的指示器。
- 最终,为了把 action 和 state 串起来,开发一些函数,这就是
reducer。再次地强调,没有任何魔法,reducer 只是一个接收 state 和 action,并返回新的 state 的函数,并且是一个纯函数。 - 而整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个
store中。
- 要想更新 state 中的数据,你需要发起一个 action。
1.2.3 redux基础介绍
1.2.3.1 action
- Action 是把数据从应用(这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过
store.dispatch()将 action 传到 store。 - Action 本质上是 JavaScript 普通对象。我们约定,action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。
1.2.3.2 store
- Store 就是把它们联系到一起的对象。Store 有以下职责:
- 维持应用的 state;
- 提供
getState()方法获取 state; - 提供
dispatch(action)方法更新 state; - 通过
subscribe(listener)注册监听器; - 通过
subscribe(listener) 返回的函数注销监听器。
- 强调一下 Redux 应用只有一个单一的 store。当需要拆分数据处理逻辑时,你应该使用 reducer 组合 而不是创建多个 store。
1.2.3.3 reducer
- Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。
- reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。
- 整个应用只有一个单一的 reducer 函数:这个函数是传给 createStore 的第一个参数。一个单一的 reducer 最终需要做以下几件事:
- reducer 第一次被调用的时候,state 的值是 undefined。reducer 需要在 action 传入之前提供一个默认的 state 来处理这种情况。
- reducer 需要先前的 state 和 dispatch 的 action 来决定需要做什么事。
- 假设需要更改数据,应该用更新后的数据创建新的对象或数组并返回它们。
- 如果没有什么更改,应该返回当前存在的 state 本身。
1.3 安装redux
- 命令如下:
npm install --save redux
2. redux入门例子
- 直接从官网拷贝的例子,例子地址:
https://www.redux.org.cn/. - 例子如下:

import { createStore } from 'redux';/*** 这是一个 reducer,形式为 (state, action) => state 的纯函数。* 描述了 action 如何把 state 转变成下一个 state。** state 的形式取决于你,可以是基本类型、数组、对象、* 甚至是 Immutable.js 生成的数据结构。惟一的要点是* 当 state 变化时需要返回全新的对象,而不是修改传入的参数。** 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)* 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。*/ function counter(state = 0, action) {switch (action.type) {case 'INCREMENT':return state + 1;case 'DECREMENT':return state - 1;default:return state;} }// 创建 Redux store 来存放应用的状态。 // API 是 { subscribe, dispatch, getState }。 let store = createStore(counter);// 可以手动订阅更新,也可以事件绑定到视图层。 store.subscribe(() =>console.log(store.getState()) );// 改变内部 state 惟一方法是 dispatch 一个 action。 // action 可以被序列化,用日记记录和储存下来,后期还可以以回放的方式执行 store.dispatch({ type: 'INCREMENT' });// 1 store.dispatch({ type: 'INCREMENT' });// 2 store.dispatch({ type: 'DECREMENT' });// 1 - 效果如下:

3. redux入门例子——优化1(reducer 和 store拆开)
3.1 想要实现的效果
-
因为上面的简单例子中的state没有在页面上渲染,所以简单优化一下,实现页面渲染操作,想呈现的效果如下:

-
如果用纯react写的话,很简单,代码如下:
import { useState } from "react";function CountNum(){const [count,setCount] = useState(0);function add(){setCount(count => count+1);}function subtract(){setCount(count => count-1);}return(<div>当前数字是:{count}<br /><br /><button onClick={add}>点我 +1</button> <br /><br /><button onClick={subtract}>点我 -1</button></div>) } export default CountNum; -
但我们目的是用redux实现,所以继续……
3.2 代码设计
- 项目结构,如下:

- store.js 和 countReducer.js 如下:

- CountNumRedux.jsx 组件如下:

- 看效果,有问题

怎么重新渲染?继续……
3.3 添加 重新渲染
-
使用
useEffect进行重新渲染,核心代码如下:useEffect(()=>{store.subscribe(()=>{console.log('订阅更新,打印2-----',store.getState());setCount(store.getState());}); });
-
然后再看效果:

-
关于useEffect ,可以看下面的文章:
React中组件通信02——消息订阅与发布、取消订阅以及卸载组件时取消订阅.
3.4 附代码
-
countReducer.js
/*** 这是一个 reducer,形式为 (state, action) => state 的纯函数。* 描述了 action 如何把 state 转变成下一个 state。** state 的形式取决于你,可以是基本类型、数组、对象、* 甚至是 Immutable.js 生成的数据结构。惟一的要点是* 当 state 变化时需要返回全新的对象,而不是修改传入的参数。** 下面例子使用 `switch` 语句和字符串来做判断,但你可以写帮助类(helper)* 根据不同的约定(如方法映射)来判断,只要适用你的项目即可。*/function countReducer(state = 0,action){console.log(`state:${state}---action:${action}---type:${action.type}`);switch (action.type){case 'INCREMENT':return state + 1;case 'DECREMENT':return state - 1;default:return state;} } export default countReducer; -
store.js
import { createStore } from 'redux';import countReducer from './countReducer.js'const store = createStore(countReducer);export default store; -
CountNumRedux.jsx
import { useState,useEffect } from "react"; import store from '../redux/store'function CountNumRedux(){const [count,setCount] = useState(0);function add(){// setCount(count => count+1);//派发action 改变内部 state 惟一方法是 dispatch 一个 action。store.dispatch({ type: 'INCREMENT' });}function subtract(){// setCount(count => count-1);store.dispatch({ type: 'DECREMENT' });}// 可以手动订阅更新,也可以事件绑定到视图层。// store.subscribe(() =>// console.log('订阅更新,打印1-----',store.getState())// );useEffect(()=>{store.subscribe(()=>{console.log('订阅更新,打印2-----',store.getState());setCount(store.getState());});});return(<div>当前数字是:{count} 当前数字是:{store.getState()} <br /><br /><button onClick={add}>点我 +1</button> <br /><br /><button onClick={subtract}>点我 -1</button></div>) }export default CountNumRedux;
4. redux入门例子——优化2(拆出action)
4.1 关于action的其他说明
- 看官网怎么说:
- Action 本质上是 JavaScript 普通对象。我们约定,action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作。多数情况下,type 会被定义成字符串常量。当应用规模越来越大时,建议使用单独的模块或文件来存放 action。
- 除了 type 字段外,action 对象的结构完全由你自己决定。比如下面的:
更多参考可看:https://github.com/redux-utilities/flux-standard-action.{type: ADD_TODO,text: 'Build my first Redux app'}{type: TOGGLE_TODO,index: 5} - 在 Redux 中的 action 创建函数只是简单的返回一个 action。如下:

4.2 优化——拆出action
- 根据官网上说的,做个简单优化,改动点如下:

效果就不展示了,因为这个还能继续优化,如下……
4.3 优化——动态加减数字
4.3.1 优化看效果
- 如下:


- 效果如下:

4.3.2 附代码
-
代码在上面基础上做了简单的调整,action的type抽出了变量,直接给代码了,如下:
-
countConst.js
//定义常量export const INCREMENT = 'INCREMENT'; //加 export const DECREMENT = 'DECREMENT'; //减 -
countAction.js
// //加的时候 // function incrementNum(){ // return { type: 'INCREMENT' }; // }// //减的时候 // function decrementNum(){ // return { type: 'DECREMENT' }; // }import {INCREMENT,DECREMENT} from './countConst.js'//加的时候 function incrementNum(number){return { type: INCREMENT,number:number }; }//减的时候 function decrementNum(number){return { type: DECREMENT,number:number }; }export default{incrementNum,decrementNum} -
CountNumRedux.jsx
import { useState,useEffect,useRef, createRef } from "react"; import store from '../redux/store' import countAction from '../redux/countAction'function CountNumRedux(){const [count,setCount] = useState(0);const numberRef = createRef();function add(){// setCount(count => count+1);//派发action 改变内部 state 惟一方法是 dispatch 一个 action。// store.dispatch({ type: 'INCREMENT' });// store.dispatch(countAction.incrementNum());// console.log(numberRef.current.value);let number = numberRef.current.value;// console.log(typeof number); //stringstore.dispatch(countAction.incrementNum(parseInt(number)));}function subtract(){let number = parseInt(numberRef.current.value);store.dispatch(countAction.decrementNum(number));}useEffect(()=>{store.subscribe(()=>{console.log('订阅更新,打印2-----',store.getState());setCount(store.getState());});});return(<div>当前数字是:{count} 当前数字是:{store.getState()} <br />浮动数字:<input type="number" ref={numberRef}/><br /><br /><button onClick={add}>点我 加数</button> <br /><br /><button onClick={subtract}>点我 减数</button></div>) }export default CountNumRedux; -
countReducer.js
import {INCREMENT,DECREMENT} from './countConst.js'function countReducer(state = 0,action){console.log(`state:${state}---action:${action}---type:${action.type}---number${action.number}`);switch (action.type){case INCREMENT:// return state + 1;return state + action.number;case DECREMENT:// return state - 1;return state - action.number;default:return state;} } export default countReducer;
相关文章:
React(react18)中组件通信04——redux入门
React(react18)中组件通信04——redux入门 1. 前言1.1 React中组件通信的其他方式1.2 介绍redux1.2.1 参考官网1.2.2 redux原理图1.2.3 redux基础介绍1.2.3.1 action1.2.3.2 store1.2.3.3 reducer 1.3 安装redux 2. redux入门例子3. redux入门例子——优…...
最新AI创作系统+ChatGPT网站源码+支持GPT4.0+支持ai绘画+支持国内全AI模型
一、AI创作系统 SparkAi系统是基于很火的GPT提问进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT系统?小编这里写一个详细图文教程吧&#x…...
react+umi项目中引入antd组件报错:“Button”不能用作 JSX 组件解决方案
具体报错信息 “Button”不能用作 JSX 组件。 Its type ‘(props: IProps) > React.ReactElement’ is not a valid JSX element type. 不能将类型“(props: IProps) > React.ReactElement”分配给类型“(props: any, deprecatedLegacyContext?: any) > ReactNode”。…...
常用算法模板
目录 快读、快输 快读、快输 #include <cstdio> #define Re register int #define LD double// 读整数 inline void in(Re &x) {int f 0; x 0; char c getchar();while (c < 0 || c > 9) f | c -, c getchar();while (c > 0 && c < 9) x …...
最全跨境独立站建站详细步骤解析
对于跨境电商卖家来说,无论是规避“鸡蛋放在同一个篮子里”的风险,还是追求更多的销售额和利润,多平台、多站点的布局都是其至关重要的战略。加之市场的变化带来了新的发展机遇,这也使得如今很多出海企业都在抢占独立站新风口。然…...
提升群辉AudioStation音乐体验,实现公网音乐播放
文章目录 本教程解决的问题是:按照本教程方法操作后,达到的效果是本教程使用环境:1 群晖系统安装audiostation套件2 下载移动端app3 内网穿透,映射至公网 很多老铁想在上班路上听点喜欢的歌或者相声解解闷儿,于是打开手…...
虹科分享 | 谷歌Vertex AI平台使用Redis搭建大语言模型
文章来源:虹科云科技 点此阅读原文 基础模型和高性能数据层这两个基本组件始终是创建高效、可扩展语言模型应用的关键,利用Redis搭建大语言模型,能够实现高效可扩展的语义搜索、检索增强生成、LLM 缓存机制、LLM记忆和持久化。有Redis加持的大…...
VS Code 代码跳转到定义(.js 和 .vue文件跳转)
vscode 代码跳转到定义(.js 和 .vue文件跳转) 在日常的开发工作中,我们经常需要跳转到方法或变量的定义处,以便更好地理解和修改代码。VS Code 是目前比较流行的开发工具,然而它默认情况下并不支持这个功能,…...
华为云云耀云服务器L实例评测 | Docker 部署 Reids容器
文章目录 一、使用Docker部署的好处二、Docker 与 Kubernetes 对比三、云耀云服务器L实例 Docker 部署 Redis四、可视化工具连接Redis⛵小结 一、使用Docker部署的好处 Docker的好处在于:在不同实例上运行相同的容器 Docker的五大优点: 持续部署与测试…...
聚观早报 | 杭州亚运开幕科技感拉满;腾讯官宣启动「青云计划」
【聚观365】9月25日消息 杭州亚运开幕科技感拉满 腾讯官宣启动「青云计划」 FF任命新全球CEO 比亚迪夺得多国销冠 iPhone 15/15 Pro销售低于预期 杭州亚运开幕科技感拉满 杭州第19届亚洲运动会开幕式23日晚在杭州奥体中心主体育馆举行,这届开幕式可谓科技感拉…...
Linux Gnome桌面无法打开终端Terminal
文章目录 前言排障解决方式一解决方式二 前言 由于不知名的原因,导致gonme桌面里打开terminal一直转圈,无法打开。 这里我的故障是已知的,我是因为要把英文改为中文。但是界面依旧是英文,同时导致终端无法打开。 此方式centos d…...
MySQL学习笔记15
1、内连接查询(重点): 基本语法: select 数据表1.字段列表,数据表2.字段列表 from 数据表1 inner join 数据表2 on 连接条件; 案例:获取产品表中每个产品的分类信息: mysql> select * from tb_goods …...
6、SpringBoot_项目的打包与运行
七、SpringBoot项目的打包与运行 1.目前项目怎么运行的 通过浏览器访问idea 将jar部署到服务器 2.maven 打包项目 命令 mvn package使用命令后会得到如下的jar 3.程序运行 命令 java -jar 项目.jar启动如下 4.springboot打包需要插件 插件 <plugin><group…...
图像语义分割概述
图像语义分割概述 一、图像语义分割概念 图像语义分割(Image Semantic Segmentation)是一项计算机视觉任务,其目标是将输入的图像分割成多个区域,并为每个像素分配一个语义类别标签,以表示该像素属于图像中的哪个物体…...
ViT细节与代码解读
最近看到两篇解读ViT很好的文章,备忘记录一下: 先理解细节 1:再读VIT,还有多少细节是你不知道的 再理解代码 1:ViT源码阅读-PyTorch - 知乎...
Linux中软链接与硬链接的作用、区别、创建、删除
1、软链接与硬链接的作用 (1)软链接 软链接是Linux中常用的命令,它的功能是某一文件在另外一个位置建立一个同步的链接,相当于C语言中的指针,建立的链接直接指向源文件所在的地址,软链接不会另外占用资源,当同一文件需要在多个位置被用到的时候,就会使用到软连接。 …...
第一章:最新版零基础学习 PYTHON 教程(第十四节 - Python 条件和循环语句–Python 中的 with 语句)
在Python中,with语句用于异常处理,使代码更简洁、更具可读性。它简化了文件流等公共资源的管理。观察以下代码示例,了解使用 with 语句如何使代码更简洁。 Python3 # 文件处理# 1) 不使用with语句 file = open(文件路径, w) # 打开文件以进行写操作 file.write(你好,世界…...
安科瑞AMC16-DETT铁塔jizhan直流电能计量模块,直流计量用
安科瑞虞佳豪壹捌柒陆壹伍玖玖零玖叁 9月20日,在杭州亚运会火炬传递的现场,不少人通过网络与亲友连线,共同见证火炬传递的历史时刻。上午6时,杭州铁塔的一线通信保障人员共27人就已经在本次火炬传递收官点位奥体中心西广场附近&a…...
WebGL笔记:WebGL中JS与GLSL ES 语言通信,着色器间的数据传输示例:js控制绘制点位
js改变点位,动态传值 <canvas id"canvas"></canvas><!-- 顶点着色器 --><script id"vertexShader" type"x-shader/x-vertex">attribute vec4 a_Position;void main() {// 点位gl_Position a_Position;// 尺…...
一文读懂 Redis 缓存系统
【摘要】本文介绍了Redis缓存原理、详细解析了缓存模型、缓存一致性和缓存异常场景。 【作者】李杰,专注于Java虚拟机技术、云原生技术领域的探索与研究。 尽管(关系型)数据库系统 (SQL) 带来了许多出色的属性,例如 ACID&#x…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...
从零手写Java版本的LSM Tree (一):LSM Tree 概述
🔥 推荐一个高质量的Java LSM Tree开源项目! https://github.com/brianxiadong/java-lsm-tree java-lsm-tree 是一个从零实现的Log-Structured Merge Tree,专为高并发写入场景设计。 核心亮点: ⚡ 极致性能:写入速度超…...
6.9本日总结
一、英语 复习默写list11list18,订正07年第3篇阅读 二、数学 学习线代第一讲,写15讲课后题 三、408 学习计组第二章,写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语:复习l默写sit12list17&#…...
RKNN开发环境搭建2-RKNN Model Zoo 环境搭建
目录 1.简介2.环境搭建2.1 启动 docker 环境2.2 安装依赖工具2.3 下载 RKNN Model Zoo2.4 RKNN模型转化2.5编译C++1.简介 RKNN Model Zoo基于 RKNPU SDK 工具链开发, 提供了目前主流算法的部署例程. 例程包含导出RKNN模型, 使用 Python API, CAPI 推理 RKNN 模型的流程. 本…...
[QMT量化交易小白入门]-六十二、ETF轮动中简单的评分算法如何获取历史年化收益32.7%
本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。 QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。 文章目录 相关阅读1. 策略概述2. 趋势评分模块3 代码解析4 木头…...
