react、redux、redux-thunk中间件实现异步操作总结

前言

在用react开发项目时,难免会遇到一些复杂的情况。例如状态管理这一块,组件多的时候组件之间相互联系很麻烦,通常利用redux来进行统一状态管理。而redux默认的是同步方法,并且当异步请求后台接口时,我们需要根据结果执行对应的操作,这时我们可以利用中间件redux-thunk来实现。下面是我学习后的总结。

redux的工作原理:

简单复习一下。说白了,store就是存储state的仓库,action通过dispatch与store取得联系,告诉reducers要进行什么操作,然后对应的reducer实际操作state,store将结果反馈给组件。
react、redux、redux-thunk中间件实现异步操作总结_第1张图片

react-redux的项目结构

合理搭建项目结构方便维护、开发。这是我比较喜欢的一款:
react、redux、redux-thunk中间件实现异步操作总结_第2张图片
src下的components是用来放公用组件的,如header、footer、消息框。
containers中是每个页面的大容器,而每个页面又有各自的组件,最终聚合在index里面。其中,App又把所有容器聚合,放到src目录下的入口文件index.js里
redux里又分为actions、middleware、reducers文件夹,以及唯一的store
这样就是一个基本结构了

异步请求实际场景

下面是我仿大众点评App时遇到的场景:下拉时显示更多商品。
这里需要执行一个异步操作向后台请求数据,得到结果后更新组件视图。那么这时就需要用到redux-thunk这个中间件了。
react、redux、redux-thunk中间件实现异步操作总结_第3张图片
中间件可以理解为一个函数,对store.dispatch进行了改造,在发出 Action 后按顺序依次执行中间件实现其他功能,最后执行 Reducer 操作state。大部分功能都有现成的,例如这里的redux-thunk。
为什么要用redux-thunk呢?因为dispatch本身接收的是一个对象,例如向后台请求数据时,我们不知道请求是否在进行中,不知道结果是成功还是失败,应该执行哪个action,并且redux默认是同步方法。我们想要的情况是 当接受到结果时再继续往下执行。redux-thunk的作用就是使dispatch接收一个函数,这样我们就可以执行异步操作,向后台请求数据,根据结果执行对应action,所以这里需要细化actions。

/redux/store.js

import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers";
// applyMiddleware(...middlewares)会让中间件连成一个数组,按顺序依次执行
const middlewares = [thunk]
const store = createStore(rootReducer, applyMiddleware(...middlewares));
export default store;

/redux/actions/home.js

import http from '../../utils/http'
  //获取猜你喜欢列表请求
export const GET_LIKES_SUCCESS = "GET_LIKES_SUCCESS"
export const GET_LIKES_FAIL = "GET_LIKES_FAIL"

export const HomeActions = {
  //加载猜你喜欢列表数据
  getLikes: () => (dispatch,getState) => {
      const { pageSize,perPage } = getState().home.likes;
      // 封装好ajax的http请求
      http.get("/getLikes",{perPage,pageSize}).then((res) => { 
        return dispatch({
          response: res.data,
          type: GET_LIKES_SUCCESS
        })
      }).catch((err)=> {
        return dispatch({
          type: GET_LIKES_FAIL
        })
      })
  },
  other: () => {
	...
  }
}

/container/Home/index.js

这个场景就是当子组件下拉到底时,触发父组件的loadMore方法,该方法会先请求数据,等后台返回结果后再执行action

import React, { Component } from 'react';
import List from './components/List'
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
// 加载actions
import { HomeActions } from "../../redux/actions/home";

class Home extends Component {
  loadMore = () => {
  // 注意这里HomeActions是节点流中的
    this.props.HomeActions.getLikes()
  }
  render() {
    const {likes} = this.props
    return (
      <div className="container">
        <List data = {likes} getLikes={this.loadMore}/>
      </div>
    );
  }
}
// 这两个方法遍历state和action分发给组件
const mapStateToProps = (state, props) => {
  return {
    likes: state.home.likes,
  }
}

const mapDispatchToProps = dispatch => {
  return {
    HomeActions: bindActionCreators(HomeActions, dispatch)
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Home)

/redux/reducers/home.js

import { combineReducers} from "redux"
//初始数据
const initialState = {
  likes: {
    perPage: 0,
    pageSize: 5,
    goods: [],
    fail: false
  },
  discounts: {
    fail: false,
    goods: []
  }
};
//猜你喜欢reducer
const likes = (state = initialState.likes, action) => {
  switch (action.type) {
    case "GET_LIKES_SUCCESS":
      return {
        type:  "GET_LIKES_SUCCESS",
        ...state,
        pageCount: state.pageSize*(state.perPage+1),
        goods: state.goods.concat(action.response.data.goods)
      }
    case "GET_LIKES_FAIL":
      return {
        type: "GET_LIKES_FAIL",
        ...state,
        fail: true
      }
    default:
      return state
  }
}
//其他reducer
const other = (state = initialState.discounts, action) => {
  ...
};

const reducer = combineReducers({
  other,
  likes
})
export default reducer

以上就是一个完整的流程。下面是我的实际应用。
react、redux、redux-thunk中间件实现异步操作总结_第4张图片
打印一下后端返回的数据,根据结果 执行成功后的action。

在Home组件里的List子组件注入data,也就是这个组件需要用到的那部分state。打印一下新的state:

  render() {
    const {data} = this.props 
    console.log(data)
    ...

react、redux、redux-thunk中间件实现异步操作总结_第5张图片
可以看到state已经发生改变了,视图会在返回结果后刷新

以上就是我对redux项目的异步请求中间件的理解和简单应用。实际项目场景会更复杂,例如 判断是否正在请求、针对各种返回结果的处理。

你可能感兴趣的:(前端,react)