react学习 ---第十天 Redux的使用详解(二)

目录:

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状态管理选择

 

猜你喜欢

转载自blog.csdn.net/weixin_56663198/article/details/129127050
今日推荐