目录:
1 认识ReduxToolkit
2 ReduxToolkit重构
3 ReduxToolkit异步
4 connect高阶组件
5 中间件的实现原理
6 React状态管理选择
一、认识ReduxToolkit
npm install @reduxjs/toolkit react-redux
npm install react-redux
下载好后,创建store文件夹,在index.js文件里面写:
再创建一个feature(特征)文件夹来存放不同模块的文件,底下的文件按照组件名或者数据名.js来创建,之前createStore所需要的4个文件现在只需要一个js文件就可以了:
页面的index.js文件里面的写法和之前一样,需要使用react-redux的Provider来提供store:
需要使用store里面数据的组件通过从rect-redux里面获取connect来提供数据:
修改store里面的变量的方法:在counter.js里面输出了actions解构出来的两个方法addNumber,subNumber
对象可以结构,直接把action结构成 { payload }
需要调用修改store数据方法、函数的组件代码:
二、ReduxToolkit重构
三、ReduxToolkit异步
1、在store/feature/home.js里面代码
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit' import axios from 'axios' export const fetchHomeMultidataAction = createAsyncThunk( //第一个参数(fetch/homemultidata)是用来给redux知道是哪个函数被调用用的。可以是其他名称 //给一个类名,和下面的name差不多的意思 "fetch/homemultidata", async (extraInfo, { dispatch, getState }) => { // console.log(extraInfo, dispatch, getState) // 1.发送网络请求, 获取数据 const res = await axios.get("http://123.207.32.32:8000/home/multidata") // 2.取出数据, 并且在此处直接dispatch操作(可以不做) //如果不想使用extraReducers,可以在async 的异步函数里面写入参数,第一个是获取组件调用 //fetchHomeMultidataAction 时发过来的参数的,第二个是传store过来的,store可以解构获得 // dispatch、getState。这个例子里面传的参数是{name: "why", age: 18} // const banners = res.data.data.banner.list // const recommends = res.data.data.recommend.list // dispatch(changeBanners(banners)) // dispatch(changeRecommends(recommends)) // 3.返回结果, 那么action状态会变成fulfilled状态 return res.data }) const homeSlice = createSlice({ name: "home", initialState: { banners: [], recommends: [] }, reducers: { changeBanners(state, { payload }) { state.banners = payload }, changeRecommends(state, { payload }) { state.recommends = payload } }, // extraReducers: { //里用到的是计算属性名,第一个是在发送请求且在获得服务器信息前获得的信息 [fetchHomeMultidataAction.pending](state, action) { console.log("fetchHomeMultidataAction pending") }, //从服务器请求获得了信息,在这里向store的state里面更新数据 [fetchHomeMultidataAction.fulfilled](state, { payload }) { state.banners = payload.data.banner.list state.recommends = payload.data.recommend.list }, //从服务器获取信息发生错误的时候会使用这个 [fetchHomeMultidataAction.rejected](state, action) { console.log("fetchHomeMultidataAction rejected") } } //下面这个和上面的extraReducers一样,只是写法不一样 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 { changeBanners, changeRecommends } = homeSlice.actions export default homeSlice.reducer
2、需要使用异步方法的组件里面:
import React, { PureComponent } from 'react' // import axios from "axios" import { connect } from "react-redux" import { addNumber } from '../store/features/counter' import { fetchHomeMultidataAction } from '../store/features/home' // import store from "../store" // import { changeBanners, changeRecommends } from '../store/features/home' export class Home extends PureComponent { componentDidMount() { this.props.fetchHomeMultidata() // axios.get("http://123.207.32.32:8000/home/multidata").then(res => { // const banners = res.data.data.banner.list // const recommends = res.data.data.recommend.list // store.dispatch(changeBanners(banners)) // store.dispatch(changeRecommends(recommends)) // }) } addNumber(num) { this.props.addNumber(num) } render() { const { counter } = this.props return ( <div> <h2>Home Counter: {counter}</h2> <button onClick={e => this.addNumber(5)}>+5</button> <button onClick={e => this.addNumber(8)}>+8</button> <button onClick={e => this.addNumber(18)}>+18</button> </div> ) } } const mapStateToProps = (state) => ({ counter: state.counter.counter }) const mapDispatchToProps = (dispatch) => ({ addNumber(num) { dispatch(addNumber(num)) }, fetchHomeMultidata() { dispatch(fetchHomeMultidataAction({name: "why", age: 18})) } }) export default connect(mapStateToProps, mapDispatchToProps)(Home)
4
四、connect高阶组件
connect高阶函数的调用原理(低耦合,需要在app的index里面写):
StoreContext.js里面的内容
import { createContext } from "react"; export const StoreContext = createContext()
index。js里面的内容
export { StoreContext } from "./StoreContext" export { connect } from "./connect"
connect.js里面的内容:
// connect的参数: // 参数一: 函数 // 参数二: 函数 // 返回值: 函数 => 高阶组件 import { PureComponent } from "react"; import { StoreContext } from "./StoreContext"; //由于这里的耦合度太高,如果想要往npm里面上传自己的包,我们就不能用../store来导入store //于是,我们就需要同过向store的Provider一样的主题来提供store。获得的store在constructor的参 //数context // import store from "../store" export function connect(mapStateToProps, mapDispatchToProps, store) { // 高阶组件: 函数 return function(WrapperComponent) { class NewComponent extends PureComponent { constructor(props, context) { super(props) this.state = mapStateToProps(context.getState()) } componentDidMount() { this.unsubscribe = this.context.subscribe(() => { // this.forceUpdate() 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}/> } } NewComponent.contextType = StoreContext return NewComponent } }
五、中间件的实现原理
中间件的实现原理:
六、React状态管理选择