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

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) => {
// 第一个can
	const 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;
}

http://www.kler.cn/news/136284.html

相关文章:

  • Fast Simulation of Mass-Spring Systems in Rust 论文阅读
  • echarts:导入excel生成桑葚图
  • 【C++】进阶:类相关特性的深入探讨
  • 改变组件默认上报事件的参数,添加额外参数
  • [旧日谈]高清画面撕裂问题考
  • WASM 使用说明23事(RUST实现)
  • 【左程云算法全讲11】贪心算法 并查集
  • k8s的高可用集群搭建,详细过程实战版
  • 原型模式-C++实现
  • 《崩坏:星穹铁道》1.5仙舟罗浮-绥园全宝箱攻略
  • 【Linux】软连接和硬链接:创建、管理和解除链接的操作
  • Flutter 中数据存储的四种方式
  • 机器学习笔记 - Ocr识别中的CTC算法原理概述
  • JVM:内存模型、内存分配机制、内存分配冲突、JVM垃圾标记算法、JVM1.8增加元数据区缘由
  • python中sklearn库在数据预处理中的详细用法,及5个常用的Scikit-learn(通常简称为 sklearn)程序代码示例
  • 机器学习第8天:SVM分类
  • 创新工具 | 教你6步用故事板设计用户体验事半功倍
  • 【计算机网络笔记】路由算法之链路状态路由算法
  • 集合的自反关系和对称关系
  • Wireshark 截取指定端口海量包分析
  • 【Spring Boot】如何集成Redis
  • 【心得】基于flask的SSTI个人笔记
  • Oracle 数据库中 查询时如何使用日期(时间)作为查询条件
  • 使用Python的turtle模块绘制玫瑰花图案(含详细Python代码与注释)
  • C++二分查找算法:132模式枚举3简洁版
  • IDEA版SSM入门到实战(Maven+MyBatis+Spring+SpringMVC) -Maven依赖管理,版本号管理,继承和聚合