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如何管理

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

勒索攻击风起云涌,Sodinokibi深度分析

前言 Sodinokibi勒索病毒&#xff0c;又称为REvil勒索病毒&#xff0c;这款勒索病毒最早在国内被发现是2019年4月份&#xff0c;笔者在早期分析这款勒索病毒的时候就发现它与其他勒索病毒不同&#xff0c;于是被笔者称为GandCrab勒索病毒的“接班人”&#xff0c;为什么它是Ga…

Servlet JSP-Eclipse安装配置Maven插件

Maven 是一款比较常用的 Java 开发拓展包&#xff0c;它相当于一个全自动 jar 包管理器&#xff0c;会导入用户开发时需要使用的相应 jar 包。使用 Maven 开发 Java 程序&#xff0c;可以极大提升开发者的开发效率。下面我就跟大家介绍一下如何在 Eclipse 里安装和配置 Maven 插…

哈夫曼树的学习以及实践

哈夫曼树 哈夫曼树的基本了解哈夫曼树的基本概念创建霍夫曼树的思路编码构建的思路代码实现创建HuffmanTree结点初始化HuffmanTree创建霍夫曼树霍夫曼树编码 哈夫曼树的基本了解 给定 n 个 权值 作为 n 个 叶子节点&#xff0c;构造一颗二叉树&#xff0c;若该树的 带权路径长…

Redis相关介绍

概念 Redis&#xff1a;非关系型数据库&#xff08;non-relational)&#xff0c;Mysql是关系型数据库(RDBMS) Redis是当今非常流行的基于KV结构的作为Cache使用的NoSQL数据库 为什么使用NoSQL 关系型 数据库无法应对每秒上万次 的读写请求 表中的存储记录 数量有限 无法简单…

政安晨:在Jupyter中【示例演绎】Matplotlib的官方指南(四){Artist tutorial}·{Python语言}

第一次看到我的演绎文章的小伙伴&#xff0c;如果需要&#xff0c;可以先看一下我这篇文章的前三篇&#xff0c;包括准备环境等等&#xff1a; 政安晨&#xff1a;在Jupyter中【示例演绎】Matplotlib的官方指南&#xff08;一&#xff09;{Pyplot tutorial}https://blog.csdn.…

Vulnhub靶场 DC-8

目录 一、环境搭建 二、信息收集 1、主机发现 2、指纹识别 三、漏洞复现 1、SQL注入 sqlmap工具 2、dirsearch目录探测 3、反弹shell 4、提权 exim4 5、获取flag 四、总结 一、环境搭建 Vulnhub靶机下载&#xff1a; 官网地址&#xff1a;https://download.vulnhub.com/dc/DC-…

知识图谱 多模态学习 2024 最新综述

知识图谱遇见多模态学习&#xff1a;综述 论文题目&#xff1a;Knowledge Graphs Meet Multi-Modal Learning: A Comprehensive Survey 论文链接&#xff1a;http://arxiv.org/abs/2402.05391 项目地址&#xff1a;https://github.com/zjukg/KG-MM-Survey 备注&#xff1a;55…

读十堂极简人工智能课笔记01_人工智能简史

1. 2400年前 1.1. 希腊罗德岛 1.1.1. 是个神奇的岛屿&#xff0c;以机械发明著称&#xff0c;包括真人大小的、大理石制成的自动机 1.1.2. 早在罗马帝国诞生之前&#xff0c;公元前400多年的希腊就有这样的机器人技术&#xff0c;似乎不可思议 2. 公元前970到前931年 2.1.…

LAXCUS分布式操作系统目标:软件算力入口

英伟达现在的市值相当于整个中国股市&#xff01;说明了什么&#xff1f; AI 大潮下&#xff0c;算力就是生产力&#xff0c;也是未来 20 年一切产业的基础&#xff0c;英伟达已经把住硬件算力入口&#xff0c;LAXCUS 分布式操作系统瞄准软件算力入口&#xff0c;做好了&#…

网安常用的三个攻击方式

1.渗透测试执行标准&#xff08;PTES&#xff09; 渗透测试执行标准由7个部分组成&#xff0c;包括前期交互、情报收集、威胁建模、漏洞分析、渗透利用、后渗透、撰写报告。在中国&#xff0c;渗透测试必须经过授权&#xff0c;否则就违背了网络安全法。前期交互主要指开展渗透…

docker 1:介绍

docker 1&#xff1a;介绍 docker解决哪些问题&#xff1a; 传统APP在安装到不同电脑的时候可能会遇到依赖问题&#xff0c;比如缺少VS 20xx&#xff0c;软件无法运行”的情况。docker使用容器技术将软件 依赖​打包为image包发布&#xff0c;解决了依赖问题。docker有一个官…

腾讯云4核8G服务器性能如何?支持多少用户访问?

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