The scheme of asynchronous operation (network request) in Redux

Asynchronous operations in Redux

In the previous simple case, the counter saved in redux is a locally defined data

We can dispatch action directly through synchronous operations, and the state will be updated immediately.

But in real development, a lot of data saved in redux may come from the server, we need to make asynchronous requests, and then save the data to redux.

When we learned about network requests before, we said that we have two options for network requests. We can send network requests directly in the hook function of the component, and then store the data in the store; we can also directly generate network requests in the store.


Asynchronous operations in components

The network request can be sent in the life cycle function componentDidMount of the class component, so we can have this structure :

insert image description here

I have now completed the following case operations :

Create a component Category, send a network request in this component, and get the data of banners and recommends;

Display the data of banners and recommends in the About component;

First, you need to create the action to be dispatched, and the corresponding reducer

// store/actionCreators.jsx

import {
    
     CHANGE_BANNERS, CHANGE_RECOMMENDS } from "./constants"

export const changeBannersAction = (banners) => ({
    
    
  type: CHANGE_BANNERS,
  banners
})
export const changeRecommendsAction = (recommends) => ({
    
    
  type: CHANGE_RECOMMENDS,
  recommends
})
// store/reducer.jsx

import {
    
     CHANGE_BANNERS, CHANGE_RECOMMENDS } from "./constants"

const initialState = {
    
    
  banners: [],
  recommends: []
}

export default function reducer(state = initialState, action) {
    
    
  switch(action.type) {
    
    
    case CHANGE_BANNERS:
      return {
    
    ...state, [banners: action.banners}
    case CHANGE_RECOMMENDS:
      return {
    
    ...state, recommends: action.recommends}
    default: 
      return state
  }
}

Send a network request in the Categroy component, and modify the banners and recommends in the store to the data after the network request

import React, {
    
     PureComponent } from 'react'
import axios from 'axios'
import {
    
     connect } from 'react-redux'
import {
    
     changeBannersAction, changeRecommendsAction } from '../store/actionCreators'

export class Category extends PureComponent {
    
    

  componentDidMount() {
    
    
    // 发送网络请求, 获取到banners和recommends数据
    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
      console.log(banners, recommends)

      // 调用映射过来的方法, 修改banners和recommends 
      this.props.changeBanners(banners)
      this.props.changeRecommends(recommends)
    })
  }

  render() {
    
    
    return (
      <div>Category</div>
    )
  }
}

// 映射方法用于修改store中的banners和recommends
const mapDispatchToProps = (dispatch) => ({
    
    
  changeBanners(banners) {
    
    
    dispatch(changeBannersAction(banners))
  },
  changeRecommends(recommends) {
    
    
    dispatch(changeRecommendsAction(recommends))
  }
})

export default connect(null, mapDispatchToProps)(Category)

Currently, the data stored in the store is the data obtained by the network request, and then it will be displayed on the About page

import React, {
    
     PureComponent } from 'react'
import {
    
     connect } from 'react-redux'

export class About extends PureComponent {
    
    

  render() {
    
    
    // 在props中获取到映射过来的数据
    const {
    
     banners, recommends } = this.props

    return (
      <div>
        <h2>轮播图展示</h2>
        <ul>
          {
    
    
            banners.map(item => {
    
    
              return <li key={
    
    item.acm}>{
    
    item.title}</li>
            })
          }
        </ul>

        <h2>推荐数据展示</h2>
        <ul>
          {
    
    
            recommends.map(item => {
    
    
              return <li key={
    
    item.acm}>{
    
    item.title}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

const mapStateToProps = (state) => ({
    
    
  banners: state.banners,
  recommends: state.recommends
})

// 表示将数据映射到About组件中
export default connect(mapStateToProps)(About)

Asynchronous operations in redux

The code above has a flaw :

We must put the asynchronous code of the network request into the life cycle of the component to complete;

In fact, the data requested by the network is also part of our state management. A better way should be to hand it over to redux for management;

insert image description here

But how can asynchronous operations be performed in redux?

The answer is to use middleware (Middleware). If you have learned the Express or Koa framework, you must be familiar with the concept of middleware;

Under normal circumstances, store.dispatch()only one object can be dispatched, and functions cannot be dispatched; if dispatch wants to dispatch functions, we must use middleware to enhance the store

使用中间件, 在redux中发送网络请求

First install the redux-thunk library and introduce middleware

Install the redux-thunk library: npm i redux-thunk, there is a middleware thunk in the library, apply the thunk middleware in the following way

import {
    
     createStore, applyMiddleware } from "redux";
import reducer from "./reducer";
// 导入中间件
import thunk from "redux-thunk";

// 应用中间件
const store = createStore(reducer, applyMiddleware(thunk))

export default store

Once applied, store.dispatch()the function can be dispatched

// 定义一个返回函数的action
export const fetchHomeMultidataAction = () => {
    
    
  function foo() {
    
    
    console.log("aaa")
  }

  return foo
}
// 派发action
const mapDispatchToProps = (dispatch) => ({
    
    
  fetchHomeMultidata() {
    
    
    // 派发一个函数, 内部返回的函数自动执行
    dispatch(fetchHomeMultidataAction())
  }
})

When the function returned in the action is automatically executed, a dispatch function and a getState function will be passed to this function;

dispatch函数: used for us to dispatch action again later;

getState函数: Considering that some of our subsequent operations need to rely on the original state, calling the getState function allows us to obtain some previous states;

We can write asynchronous network request related code in the returned function

import axios from "axios"

export const changeBannersAction = (banners) => ({
    
    
  type: CHANGE_BANNERS,
  banners
})
export const changeRecommendsAction = (recommends) => ({
    
    
  type: CHANGE_RECOMMENDS,
  recommends
})

export const fetchHomeMultidataAction = () => {
    
    
  // 派发时返回的该函数自动执行, 且传入两个参数dispatch, getState
  return (dispatch, getState) => {
    
    
    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

      // 获取到数据后在派发action
      dispatch(changeBannersAction(banners))
      dispatch(changeRecommendsAction(recommends))
    })
  }
}

Guess you like

Origin blog.csdn.net/m0_71485750/article/details/126754159