react【五】redux/reduxToolkit/手写connext
文章目录
- 1、回顾纯函数
- 2、redux
- 2.1 redux的基本使用
- 2.2 通过action修改store的数值
- 2.3 订阅state的变化
- 2.4 目录结构
- 2.5 Redux的使用过程
- 2.6 redux的三大原则
- 2.7 Redux官方图
- 3、redux在React中的使用
- 4、react-redux使用
- 4.1 react-redux的基本使用
- 4.2 异步请求 redux-thunk
- 4.3 对redux代码结构进行优化 和 redux-devtools
- 5、ReduxToolkit
- 5.1 基本使用
- 5.2 异步操作 写法1
- 5.3 异步操作 写法2
- 6、手写connext
- 7、合并中间件
- 8、React中的state如何管理
1、回顾纯函数
2、redux
2.1 redux的基本使用
pm install redux --save
- store
const { createStore } = require("redux");// 1.state数据
const initialState = {name: "kiki",age: "18",
};// 2.reducer纯函数
function reducer() {return initialState;
}// 3.创建store
const store = createStore(reducer);module.exports = store;
2.2 通过action修改store的数值
const { createStore } = require("redux");
const { ADD_NUMBER, CHANGE_NAME } = require("./constants");// 1.state数据
const initialState = {name: "kiki",num: 18,
};// 2.reducer纯函数// 两个参数
// 参数1:store目前保存的state 设置默认参数
// 参数2:本次需要更新的action
// 返回值 他的返回值作为之后存储在store的数值 因为第一次调用没有数值 所以设置默认值
function reducer(state = initialState, action) {console.log(state, action); // { name: 'kiki', num: '18' } { type: '@@redux/INIT0.n.r.y.w.j' }switch (action.type) {case ADD_NUMBER:// 这里需要创建新的对象的返回 否则页面发现state没有发生变化不会更新界面return { ...state, num: state.num + action.num };case CHANGE_NAME:return { ...state, name: action.name };default:return state;}
}// 3.创建store
const store = createStore(reducer);module.exports = store;
2.3 订阅state的变化
2.4 目录结构
2.5 Redux的使用过程
2.6 redux的三大原则
2.7 Redux官方图
3、redux在React中的使用
4、react-redux使用
yarn add react-redux
4.1 react-redux的基本使用
import React, { PureComponent } from "react";
import { connect } from "react-redux";
// import store from "../store"
import { addNumberAction, subNumberAction } from "../store/actionCreators";export class About extends PureComponent {calcNumber(num, isAdd) {if (isAdd) {console.log("加", num);this.props.addNumber(num);} else {console.log("减", num);this.props.subNumber(num);}}render() {const { counter, banners, recommends } = this.props;return (<div><h2>About Page: {counter}</h2><div><button onClick={(e) => this.calcNumber(6, true)}>+6</button><button onClick={(e) => this.calcNumber(88, true)}>+88</button><button onClick={(e) => this.calcNumber(6, false)}>-6</button><button onClick={(e) => this.calcNumber(88, false)}>-88</button></div></div>);}
}// connect()返回值是一个高阶组件
// function mapStateToProps(state) {
// return {
// counter: state.counter
// }
// }// function fn2(dispatch) {
// return {
// addNumber(num) {
// dispatch(addNumberAction(num))
// },
// subNumber(num) {
// dispatch(subNumberAction(num))
// }
// }
// }const mapStateToProps = (state) => ({counter: state.counter,banners: state.banners,recommends: state.recommends,
});const mapDispatchToProps = (dispatch) => ({addNumber(num) {dispatch(addNumberAction(num));},subNumber(num) {dispatch(subNumberAction(num));},
});// connect是高阶组件
export default connect(mapStateToProps, mapDispatchToProps)(About);
4.2 异步请求 redux-thunk
yarn add redux-thunk
4.3 对redux代码结构进行优化 和 redux-devtools
每个页面可能都会有自己的store为了方便维护,将store按照页面划分
import { createStore, applyMiddleware, compose, combineReducers } from "redux";
import thunk from "redux-thunk";import counterReducer from "./counter";
import homeReducer from "./home";
import userReducer from "./user";// 正常情况下 store.dispatch(object)
// 想要派发函数 store.dispatch(function)// 将两个reducer合并在一起
const reducer = combineReducers({counter: counterReducer,home: homeReducer,user: userReducer,
});// combineReducers实现原理(了解)
// function reducer(state = {}, action) {
// // 返回一个对象, store的state
// return {
// counter: counterReducer(state.counter, action),
// home: homeReducer(state.home, action),
// user: userReducer(state.user, action)
// }
// }// redux-devtools
// trace的功能是可以追踪源码
const composeEnhancers =window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ trace: true }) || compose;// thunk 是用来发送异步请求的增强写法
const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)));export default store;
5、ReduxToolkit
5.1 基本使用
npm install @reduxjs/toolkit react-redux
- 需要在根组件传递store的值
import React, { PureComponent } from "react";
import { connect } from "react-redux";
import { changeNumber } from "../store/features/counter";export class About extends PureComponent {changeNum(num) {this.props.changeNumber(num);}render() {const { counter } = this.props;return (<div>{counter}<button onClick={(e) => this.changeNum(5)}>+5</button></div>);}
}const mapStateToProps = (state) => ({counter: state.counter.counter,
});const mapDispatchToProps = (dispatch) => ({changeNumber(num) {dispatch(changeNumber(num));},
});export default connect(mapStateToProps, mapDispatchToProps)(About);
5.2 异步操作 写法1
import { createAsyncThunk } from "@reduxjs/toolkit";
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";// toolkit已经集成了thunk所以可以直接使用
// 第一个参数是name可以根据自己的喜好取
// 可以把这个函数看成是promise 它跟promise十分相似
export const fetchHomeMultidataAction = createAsyncThunk("fetch/homemultidata",// dispatch传递的参数是第一个 extraInfoasync (extraInfo, { dispatch, getState }) => {console.log(extraInfo);const res = await axios.get("http://123.207.32.32:8000/home/multidata");// 不能直接返回res 没办法直接对其进行序列化return res.data;}
);const homeSlice = createSlice({name: "home",initialState: {banner: [],},reducers: {changeBanner(state, { payload }) {state.banner = payload;},},// 这里是对异步操作进行操作的方法extraReducers: {[fetchHomeMultidataAction.pending](state, action) {console.log(action);},[fetchHomeMultidataAction.fulfilled](state, { payload, meta }) {// 异步操作返回的参数state.banner = payload.data.banner.list;// 在dispatch时传递的参数console.log(meta.arg);},[fetchHomeMultidataAction.rejected](state, action) {console.log("fetchHomeMultidataAction rejected");},},
});export const { changeBanner } = homeSlice.actions;
export default homeSlice.reducer;
5.3 异步操作 写法2
import { createAsyncThunk } from "@reduxjs/toolkit";
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";// toolkit已经集成了thunk所以可以直接使用
// 第一个参数是name可以根据自己的喜好取
// 可以把这个函数看成是promise 它跟promise十分相似
export const fetchHomeMultidataAction = createAsyncThunk("fetch/homemultidata",// dispatch传递的参数是第一个 extraInfoasync (extraInfo, { dispatch, getState }) => {console.log(extraInfo);const res = await axios.get("http://123.207.32.32:8000/home/multidata");// 不能直接返回res 没办法直接对其进行序列化return res.data;}
);const homeSlice = createSlice({name: "home",initialState: {banner: [],},reducers: {changeBanner(state, { payload }) {state.banner = payload;},},// 这里是对异步操作进行操作的方法// extraReducers: {// [fetchHomeMultidataAction.pending](state, action) {// console.log(action);// },// [fetchHomeMultidataAction.fulfilled](state, { payload, meta }) {// // 异步操作返回的参数// state.banner = payload.data.banner.list;// // 在dispatch时传递的参数// console.log(meta.arg);// },// [fetchHomeMultidataAction.rejected](state, action) {// console.log("fetchHomeMultidataAction rejected");// },// },extraReducers: (builder) => {builder.addCase(fetchHomeMultidataAction.pending, (state, action) => {console.log("fetchHomeMultidataAction pending");}).addCase(fetchHomeMultidataAction.fulfilled, (state, { payload }) => {state.banners = payload.data.banner.list;state.recommends = payload.data.recommend.list;});},
});export const { changeBanner } = homeSlice.actions;
export default homeSlice.reducer;
6、手写connext
// connect的参数:
// 参数一: 函数
// 参数二: 函数
// 返回值: 函数 => 高阶组件import { PureComponent } from "react";
import { StoreContext } from "./StoreContext";
// import store from "../store"// 实际上就是一个高阶函数里面嵌套一个高阶组件
export function connect(mapStateToProps, mapDispatchToProps, store) {// 高阶组件: 函数return function (WrapperComponent) {class NewComponent extends PureComponent {// 接收的第二个参数就是contextconstructor(props, context) {super(props);this.state = mapStateToProps(context.getState());}componentDidMount() {// 因为页面发生改变是connect自己内部实现的 我们自己手写的话 要手动调用this.unsubscribe = this.context.subscribe(() => {// 不能直接通过强制刷新 不然性能很低// this.forceUpdate()// 执行ToProps的方法 自己判断是否state发生了变化this.setState(mapStateToProps(this.context.getState()));});}componentWillUnmount() {this.unsubscribe();}render() {// 传递进来的两个方法进行调用 再把他们的数值传递给组件 实现了高阶组件的增强const stateObj = mapStateToProps(this.context.getState());const dispatchObj = mapDispatchToProps(this.context.dispatch);return (<WrapperComponent {...this.props} {...stateObj} {...dispatchObj} />);}}// 为了避免每次store都是需要传入进来 所以创建了一个context 在注册应用的时候就将他导入NewComponent.contextType = StoreContext;return NewComponent;};
}
7、合并中间件
8、React中的state如何管理
相关文章:

react【五】redux/reduxToolkit/手写connext
文章目录 1、回顾纯函数2、redux2.1 redux的基本使用2.2 通过action修改store的数值2.3 订阅state的变化2.4 目录结构2.5 Redux的使用过程2.6 redux的三大原则2.7 Redux官方图 3、redux在React中的使用4、react-redux使用4.1 react-redux的基本使用4.2 异步请求 redux-thunk4.3…...

.NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
前言 很多同学都不愿给电脑设动态壁纸,其中有个重要原因就是嫌它占资源过多。今天大姚分享一个.NET开源、免费(MIT license)的一个小而快并且功能强大的 Windows 动态桌面软件,支持视频和网页动画播放:DreamScene2。 …...

jsp计算机线上教学系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 JSP 计算机线上教学系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5…...

RabbitMQ的高可用机制
RabbitMQ通过多种机制提供高可用性(HA)支持,以确保消息系统的稳定性和可靠性。下面将详细介绍这些机制,并提供代码示例。 集群(Clustering) RabbitMQ的集群提供了高可用性和负载均衡。集群中的节点共享同一个Erlang分布式数据库…...

人机协同中的贝叶斯和马尔可夫
人机协同中的马尔可夫链是指在人与机器之间协同工作过程中,可能涉及到的状态转移概率模型。马尔可夫链是一种数学模型,描述了在给定当前状态下,未来状态的概率分布只依赖于当前状态,而与过去状态无关的随机过程。在人机协同工作中…...

STM32的SDIO
一.SDIO简介 SDIO,全称Secure Digital Input/Output,是一种用于在移动设备和嵌入式系统中实现输入/输出功能的接口标准。它结合了SD卡的存储功能和I/O功能,允许设备通过SD卡槽进行数据输入输出和外围设备连接。 SDIO接口通常被用于连接各种…...

Unity中的Lerp插值的使用
Unity中的Lerp插值使用 前言Lerp是什么如何使用Lerp 前言 平时在做项目中插值的使用避免不了,之前一直在插值中使用存在误区,在这里浅浅记录一下。之前看的博客或者教程还多都存在一个“永远到达不了,只能无限接近”的一个概念。可能是之前脑…...

年后上来面了一个来字节要求月薪23K,明显感觉他背了很多面试题...
最近有朋友去字节面试,面试前后进行了20天左右,包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说,80%的人都会栽在第一轮面试,要不是他面试前做足准备,估计都坚持不完后面几轮面试。 其实&…...

代码随想录算法训练营DAY20 | 二叉树 (8)
一、LeetCode 701 二叉搜索树中的插入操作 题目链接: 701.二叉搜索树中的插入操作https://leetcode.cn/problems/insert-into-a-binary-search-tree/description/ 思路:见缝插针罢辽。 class Solution {public TreeNode insertIntoBST(TreeNode root, i…...

2023年全球软件开发大会(QCon北京站2023)2月:核心内容与学习收获(附大会核心PPT下载)
本次峰会是一个汇集了最新技术趋势、最佳实践和创新思维的盛会。对于从事软件开发和相关领域的专业人士来说,参加这样的大会将有助于他们了解行业动态、提升技能水平、拓展职业视野,并与同行建立联系和合作。 本次峰会包含:AI基础架构、DevO…...

键盘输入4个数,从小到大排序
题目 键盘输入4个整数,从小到大排序 思路 代码 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h>//键盘输入4个整数,从小到大排序 int main() {int n1, n2, n3, n4;scanf_s("%d %d %d %d", &n1, &n2, &n3, &n4);…...

Day11-Linux系统iNode及链接知识及企业按哪里精讲
Day11-Linux系统iNode及链接知识及企业按哪里精讲 1. 文件核心 属性知识1.1 什么是索引节点(inode)。1.2 索引节点作用1.3 inode是怎么产生的?1.4 inode的特点?1.5 Linux系统读取文件的原理1.6 企业生产案例:No space …...

C# Thread的使用
在C#中,线程用于实现程序的并发执行。通过创建和管理多个线程,可以同时处理不同的任务或操作,从而提高程序性能和响应性。以下是如何在C#中使用线程的基本步骤: 创建新线程 // 使用System.Threading命名空间 using System.Threa…...

ETL数据集成工具DataX、Kettle、ETLCloud特点对比
ETL数据集成工具 对于数据仓库,大数据集成类应用,通常会采用ETL工具辅助完成。ETL,是英文 Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract) 、交互转换(transform) 、加载(load)至的端的过程当前的很多应…...

OpenAI:Sora视频生成模型技术报告(中文)
概述 视频生成模型作为世界模拟器 我们探索视频数据生成模型的大规模训练。具体来说,我们在可变持续时间、分辨率和宽高比的视频和图像上联合训练文本条件扩散模型。我们利用transformer架构,在视频和图像潜在代码的时空补丁上运行。我们最大的模型Sor…...

Java基于微信小程序的乐室预约小程序,附源码
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...

Linux常见指令(一)
目录 一、基本指令 1.1ls指令 1.2pwd指令 1.3cd指令 1.4touch指令 1.5mkdir指令 1.6rmdir指令、rm指令 1.7man指令 1.8cp指令 1.9mv指令 1.10cat 一、基本指令 1.1ls指令 语法 : ls [ 选项 ][ 目录或文件 ] 功能:对于目录,该命令…...

大端和小端传输字节完整版
大端和小端传输字节序 大端和小端一、最高有效位、最低有效位1.MSB(Most significant Bit)最高有效位2.LSB(Least Significant Bit)最低有效位 二、内存地址三、大端和小端四、网络字节序和主机字节序五、C#位操作符六、C#中关于大端和小端的转换七、关于负数八、关于汉字编码以…...

华为23年9月笔试原题,巨详细题解,附有LeetCode测试链接
文章目录 前言思路主要思路关于f函数的剖析Code就到这,铁子们下期见!!!! 前言 铁子们好啊!今天阿辉又给大家来更新新一道好题,下面链接是23年9月27的华为笔试原题,LeetCode上面的ha…...

ES实战--性能提升
触发冲刷的条件: 1.内存缓冲区已满 2.自上次冲刷后超过了一定时间 3.事务日志达到了一定阀值 对名为get-together的Elasticsearch索引执行优化操作,将索引中的数据段(segments)合并到指定的数量1 GET /get-together/_optimize?max_num_segm…...

解决ModuleNotFoundError: No module named ‘pysqlite2‘
目录 一、问题描述: 二、问题分析: 三、问题解决: 四、参考文章: 一、问题描述: 在重新安装的anaconda环境中自建了一个新虚拟环境,再安装完jupyter后(pip install jupyter)&am…...

腾讯云4核8G服务器够用吗?能支持多少人?
腾讯云4核8G服务器支持多少人在线访问?支持25人同时访问。实际上程序效率不同支持人数在线人数不同,公网带宽也是影响4核8G服务器并发数的一大因素,假设公网带宽太小,流量直接卡在入口,4核8G配置的CPU内存也会造成计算…...

React 的调度系统 Scheduler
原文地址1 原文地址2 其中startTime是任务开始的时间,默认是-1,任务开始时将任务开始时间赋值给了startTime, 这里意思是判断这个任务执行时间是否超过5ms(写死的)。若超过,则要交出。...

微服务OAuth 2.1认证授权Demo方案(Spring Security 6)
文章目录 一、介绍二、auth微服务代码1. SecurityConfig2. UserDetailsService3. 总结 三、gateway微服务代码1. 统一处理CORS问题 四、content微服务代码1. controller2. SecurityConfig3. 解析JWT Utils4. 总结 五、一些坑 书接上文 微服务OAuth 2.1认证授权可行性方案(Sprin…...

WSL使用Centos7发行版(rootfs)
参考 导入要与 WSL 一起使用的任何 Linux 发行版 microsoftWSL2 的 2.0 更新彻底解决网络问题install daemon and client binaries on linuxInstall Compose standalone WSL配置 在HOST中,编辑用户目录下的.wslconfig文件 我需要使用docker,测试发现a…...

ClickHouse--04--数据库引擎、Log 系列表引擎、 Special 系列表引擎
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1.数据库引擎1.1 Ordinary 默认数据库引擎1.2 MySQL 数据库引擎MySQL 引擎语法字段类型的映射 2.ClickHouse 表引擎3.Log 系列表引擎几种 Log 表引擎的共性是&#…...

docker的底层原理
概述:Docker的底层原理基于容器化技术,通过使用命名空间和控制组等技术实现资源的隔离与管理。 底层原理: 客户端-服务器架构:Docker采用的是Client-Server架构,其中Docker守护进程(daemon)运…...

有关光猫、路由器、交换机、网关的理解
前提 在了解计算机网络的过程中,出现了这四个名词:光猫、路由器、交换机、网络。有点模糊,查阅互联网相关资料,进行整理。如有错误,欢迎大家批评指正。 光猫 首先光猫是物理存在的,大家在家里应该都可以…...

图像旋转翻转变换
题目描述 给定m行n列的图像各像素点灰度值,对其依次进行一系列操作后,求最终图像。 其中,可能的操作及对应字符有如下四种: A:顺时针旋转90度; B:逆时针旋转90度; C:…...

网站常见的反爬手段及反反爬思路
摘要:介绍常见的反爬手段和反反爬思路,内容详细具体,明晰解释每一步,非常适合小白和初学者学习!!! 目录 一、明确几个概念 二、常见的反爬手段及反反爬思路 1、检测user-agent 2、ip 访问频率的限制 …...