React整理总结(五、Redux)

1.Redux核心概念

纯函数
  • 确定的输入,一定会产生确定的输出;
  • 函数在执行过程中,不能产生副作用
store

存储数据

action

更改数据

reducer

连接store和action的纯函数
将传入的state和action结合,生成一个新的state

  • dispatch派发action修改store
  • subscribe | unsubscribe订阅store的数据发生变化
// store/index.js
import { createStore } from 'redux';const initState = {msg: "hello redux"
}
/*** 定义reducer,纯函数*****/
function reducer(state = initState, action){if (action.type === "change"){return {...state, msg: action.payload.msg};}return state;
}export default const store = createStore(reducer);// store/ actionCreator.js
/**** 动态生成action *****/
export const CHANGEMSGACTION = msg => ({type: 'change', payload: {msg}});// 使用的地方
import store from "~/store";
const unsubscribe = store.subscribe(() => {console.log("::::STORE", store.getState());
})
unsubscribe();// 修改store中的数据
const MSGAction = {type: "change", payload: {msg: "hello change",}
};
store.dispatch(MSGAction);
  • combineReducer将多个reducer合并为一个reducer,达到拆分store的目的

2. Redux三大原则

单一数据源
  • 整个应用程序的state被存储在一颗object tree中,并且这个object tree只存储在一个 store中:
  • R-edux并没有强制让我们不能创建多个Store,但是那样做并不利于数据的维护;
  • 单一的数据源可以让整个应用程序的state变得方便维护、追踪、修改;
State是只读的
  • 唯一修改State的方法一定是触发action,不要试图在其他地方通过任何的方式来修改State:
  • 这样就确保了View或网络请求都不能直接修改state,它们只能通过action来描述自己想要如何修改state;
  • 这样可以保证所有的修改都被集中化处理,并且按照严格的顺序来执行,所以不需要担心race condition(竟态)的问题;
使用纯函数来执行修改
  • 通过reducer将 旧state和 actions联系在一起,并且返回一个新的State:
  • 随着应用程序的复杂度增加,我们可以将reducer拆分成多个小的reducers,分别操作不同state tree的一部分;
  • 但是所有的reducer都应该是纯函数,不能产生任何的副作用;
    在这里插入图片描述

3.react-redux的使用

  • 通过provider给整个app提供store
// App.jsx
import { Provider } from 'react-redux';
import store from '~/store';const root = document.querySelector("#root");
root.render(<Provider store={store}><App/></Provider>
)
  • 通过connect将组件和store连接。connect会返回一个高阶组件,接受的参数将store中的部分数据映射到组件
// 组件中
import React, { PureComponent } from "react";
import { connect } from "react-redux";class MyComp extends PureComponent{render(){const { msg, changeMsg } = this.props;return (<div><h2>{msg}</h2><input onChange={val => changeMsg(val)} /></div>}
}
/**** 将state映射到props,组件中props中就会有msg ****/
function mapStateToProps(state){return {msg: state.msg}
}
/*** 将修改store的函数添加到组件的props中 ***/
function mspDispatchToProps(dispatch){return {changeMsg(msg){dispatch(CHANGEMSGACTION(msg));}}
}export default connect(mapStateToProps, mapDispatchToProps)(MyComp);
  • 异步action—中间件
    • Middleware可以帮助我们在请求和响应之间嵌入一些操作的代码,比如cookie解析、日志记录、文件压缩等操作
    • createStore的第二个参数接受一个中间件,使用react-thunk使得dispatch可以派发函数,在派发的函数中可以异步更新store。
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';const reducer = (state, action) => {...return state;
}const store = createStore(reducer, applyMiddleware(thunk));// actionCreator.js
...
/**** 被派发的函数,需要返回一个函数,该函数接受两个参数dispatch,getState,*****/
const fetchHomeDataAction = () => {return (dispatch, getState) => {fetch(url).then(res => {dispatch(HOMEDATAACTION(res.data));});}
}
// 组件中
function mapDispatchToProps(dispatch){return {fetchHomeData(){dispatch(fetchHomeDataAction()); // 执行action函数}}
}
  • 使用redux-thunk
    • 在创建store时传入应用了middleware的enhance函数
      通过applyMiddleware来结合多个Middleware, 返回一个enhancer;将enhancer作为第二个参数传入到createStore中;
    • 定义返回一个函数的action:
      这里不是返回一个对象了,而是一个函数;该函数在dispatch之后会被执行;

4.Redux/toolkit

npm install @reduxjs/toolkit react-redux

  • createSlice({name, initialState, reducers:{}})接受reducer函数的对象、切片名称和初始状态值,并自动生成切片reducer,并带有相应的actions。
    • name:用户标记slice的名词, 在之后的redux-devtool中会显示对应的名词;
    • initialState:初始化值. 第一次初始化时的值;
    • reducers:相当于之前的reducer函数.对象类型,并且可以添加很多的函数;函数类似于redux原来reducer中的一个case语句;
      • 参数一:state
      • 参数二:调用这个action时,传递的action参数;
import { createSlice } from '@reduxjs/toolkit';
const CounterSlice = createSlice({name: "counter",initialState: {count: 0,},reducers: {addNumber(state, action){state.counter += action.payload;}}
});export const { addNumber } = CounterSlice.action;
export default CounterSlice.reducer;
  • configureStore包装createStore以提供简化的配置选项和良好的默认值。它可以自动组合你的 slice reducer,添加你提供的任何 Redux 中间件,redux-thunk默认包含,并启用 Redux DevTools Extension。
const store = configureStore({reducer: {counter: counterReducer;}
})
  • createAsyncThunk接受一个动作类型字符串和一个返回承诺的函数,并生成一个pending/fulfilled/rejected基于该承诺分派动作类型的 thunk
const AXIOSDataSlice = createSlice({name: 'axiosdata',initialState: {data: []},reducers: {setData(state, action){state.data = action.payload;}},extraReducers: {/**[AxiosMultidataAction.pending](state, action){state.data = action.payload;}[AxiosMultidataAction.rejected](state, action){state.data = action.payload;}**/[AxiosMultidataAction.fulfilled](state, action){state.data = action.payload;}}/*** 链式写法 *****/extraReducers: (builder) => {builder.addCase(AxiosMultidataAction.pending, (state, action) => {console.log("pending");	}).addCase(AxiosMultidataAction.fulfilled, (state, action) => {})}
})
export default AXIOSDataSlice.reducer;const AxiosMultidataAction = createAsyncThunk("axiosdata", async (extraInfo, store) => {
// 第一个canconst res = await getData();return res;
})
  • immerjs库保持数据不可变(持久化数据

5 手写connect

function connect(mapStateToProps, mapDispatchToProps){function hoc(Component){class HOCComponent extends PureComponent{constuctor(props){super(props);this.state = mapStateToProps(store.getState());}componentDidMount(){this.unsubscribe = store.subscribe(() => {//this.forceUpdate();this.setState(mapStateToProps(store.getState());})}componentWillUnmount() {this.unsubscribe();}render(){return <Component {...this.props} {...mapStateToProps(store.getState())} {...mapDispatchToProps(store.dispatch)} />}}return HOCComponent;}return hoc;
}

6. 自己实现一些中间件

  • 打印日志中间件
function log(store){const next = store.dispatch;function logAndDispatch(action) {console.log("dispatch action", action);next(action);console.log("dispatch resulte", store.getState());}store.dispatch = logAndDispatch;
}log(store);
  • 自动实现thunk
function thunk(store){const next = store.dispatch;function thunkDispatch(action) {if (typeof action === 'function') {action(store.dispatch, store.getState());} else {next(action);}}store.dispatch = thunkDispatch;
}
  • applyMiddleware的封装
function applyMiddleware(store, ...fns){fns.forEach(fn => {fn(store);})
}

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

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

相关文章

IPFoxy:什么是数据中心代理IP?好用吗?

数据中心代理是代理IP中最常见的类型&#xff0c;也被称为机房IP。这些代理服务器为用户分配不属于 ISP&#xff08;互联网服务提供商&#xff09;而来自第三方云服务提供商的 IP 地址。数据中心代理的最大优势——它们允许在访问网络时完全匿名。 如果你正在寻找海外代理IP&am…

【Java 进阶篇】揭秘 Jackson:Java 对象转 JSON 注解的魔法

嗨&#xff0c;亲爱的同学们&#xff01;欢迎来到这篇关于 Jackson JSON 解析器中 Java 对象转 JSON 注解的详细解析指南。JSON&#xff08;JavaScript Object Notation&#xff09;是一种常用于数据交换的轻量级数据格式&#xff0c;而 Jackson 作为一款优秀的 JSON 解析库&am…

js进阶笔记之原型,原型链

目录 1、原型对象 constructor 属性 对象原型 2、原型链 3、instanceof 4、原型继承 1、原型对象 面向过程就是分析出解决问题所需要的步骤&#xff0c;然后用函数把这些步骤一步一步实现&#xff0c;使用的时候再一个一个的依次调用就可以了。 面向对象是把事务分解成为…

python刷题笔记1(42例题)

1. split()函数 str.split([sep [, maxsplit]]) 分割字符串&#xff0c;返回一个数组 2. 判断子串 # 判断子串是否在主串里面&#xff0c;是则输出“Yes”&#xff0c;否则输出“No” str1 input("子串&#xff1a;") str2 input("主串:") if str1 in s…

最新绿豆APP源码苹果CMS影视插件版本/原生JAVA源码+反编译开源+免授权

源码简介&#xff1a; 最新绿豆APP源码苹果CMS影视插件版本&#xff0c;它是原生JAVA源码反编译开源免授权&#xff0c;绿豆影视对接苹果CMS&#xff0c;它可以支持多功能自定义DIY页面布局。 1、新版绿豆视频APP视频6.1插件版反编译指南及教程 2、后端插件开源&#xff0c;可…

创建 Springboot 项目

前言 创建 Spring Boot 项目是很多Java开发人员入门的重要一步&#xff01; 欢迎来到本篇关于创建 Spring Boot 项目的博客&#xff01;Spring Boot作为一个快速、便捷的开发框架&#xff0c;为我们提供了简化和加速应用程序开发的利器。 在这个数字化时代&#xff0c;快速响…

在Jupyter Lab中使用多个环境,及魔法命令简介

一、Jupyter Lab使用conda虚拟环境 1、给虚拟环境添加 ipykernel 方法一: 创建环境时直接添加ipykernel 方法&#xff1a;conda create -n 【虚拟环境名称】python3.8 ipykernel实例如下&#xff1a; conda create -n tensorflow_cpu python3.8 ipykernel 方法二&#xff…

解决Vision Transformer在任意尺寸图像上微调的问题:使用timm库

解决Vision Transformer在任意尺寸图像上微调的问题&#xff1a;使用timm库 文章目录 一、ViT的微调问题的本质二、Positional Embedding如何处理1&#xff0c;绝对位置编码2&#xff0c;相对位置编码3&#xff0c;对位置编码进行插值 三、Patch Embedding Layer如何处理四、使…

【0到1学习Unity脚本编程】第一人称视角的角色控制器

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;【0…

7.Gin 路由详解 - 路由分组 - 路由文件抽离

7.Gin 路由详解 - 路由分组 - 路由文件抽离 前言 在前面的示例中&#xff0c;我们直接将路由的定义全部写在 main.go 文件中&#xff0c;如果后面 路由越来越多&#xff0c;那将会越来越不好管理。 所以&#xff0c;下一步我们应该考虑将路由进行分组管理&#xff0c;并且将其抽…

腾讯云代金券怎么领取(腾讯云代金券在哪领取)

腾讯云代金券是可抵扣费用的优惠券&#xff0c;领券之后新购、续费、升级腾讯云相关云产品可以直接抵扣订单金额&#xff0c;节省购买腾讯云的费用&#xff0c;本文将详细介绍腾讯云代金券的领取方法和使用教程。 一、腾讯云代金券领取 1、新用户代金券【点此领取】 2、老用户…

SVN创建分支

一 从本地创建方式可指定版本号进行分支创建。 1、在本地目录右击 -----> 点击branch/tag(分支/标签) From: 源&#xff0c;可指定具体的版本号&#xff0c; To path: 可通过"..."选择分支路径 最后点击确定&#xff0c;交由服务器执行创建。 二 通过SVN客…

3D 纹理渲染如何帮助设计师有效、清晰地表达设计理念

在线工具推荐&#xff1a; 三维数字孪生场景工具 - GLTF/GLB在线编辑器 - Three.js AI自动纹理化开发 - YOLO 虚幻合成数据生成器 - 3D模型在线转换 - 3D模型预览图生成服务 定义 3D 渲染可视化及其用途 3D 可视化是一种艺术形式。这是一个机会。这是进步。借助 3D 纹理…

CNVD-2023-12632:泛微E-cology9 browserjsp SQL注入漏洞复现 [附POC]

文章目录 泛微E-cology9 browserjsp SQL注入漏洞(CNVD-2023-12632)漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 泛微E-cology9 browserjsp SQL注入漏洞(CNVD-2023-12632)漏洞复现 [附POC] 0x…

visionOS空间计算实战开发教程Day 1:环境安装和编写第一个程序

安装 截至目前visionOS还未在Xcode稳定版中开放&#xff0c;所以需要下载​​Xcode Beta版​​。比如我们可以下载Xcode 15.1 beta 2&#xff0c;注意Xcode 15要求系统的版本是macOS Ventura 13.5或更新&#xff0c;也就是说2017年的MacBook Pro基本可以勉强一战&#xff0c;基…

海外IP代理:数据中心代理IP是什么?好用吗?

数据中心代理是代理IP中最常见的类型&#xff0c;也被称为机房IP。这些代理服务器为用户分配不属于 ISP&#xff08;互联网服务提供商&#xff09;而来自第三方云服务提供商的 IP 地址。数据中心代理的最大优势——它们允许在访问网络时完全匿名。 如果你正在寻找海外代理IP&am…

【JavaEE】Servlet实战案例:表白墙网页实现

一、功能展示 输入信息&#xff1a; 点击提交&#xff1a; 二、设计要点 2.1 明确前后端交互接口 &#x1f693;接口一&#xff1a;当用户打开页面的时候需要从服务器加载已经提交过的表白数据 &#x1f693;接口二&#xff1a;当用户新增一个表白的时候&#xff0c;…

MEMS制造的基本工艺——晶圆键合工艺

晶圆键合是一种晶圆级封装技术&#xff0c;用于制造微机电系统 (MEMS)、纳米机电系统 (NEMS)、微电子学和光电子学&#xff0c;确保机械稳定和气密密封。用于 MEMS/NEMS 的晶圆直径范围为 100 毫米至 200 毫米&#xff08;4 英寸至 8 英寸&#xff09;&#xff0c;用于生产微电…

单链表(数据结构与算法)

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ &#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1…