Appearance
redux-thunk 解析
首先看下在 React 中发送异步请求获取数据
js
componentDidMount() {
  axios.get('/list.json').then((res) => {
    store.dispatch({type:FETCH_DATA,payload:res.data})
  })
}
在 componentDidMount 做了一个 ajax 数据的请求,咋一看可能没有什么问题,但是如果我们把这种异步的请求,或者把一些非常复杂的逻辑都放在组件里进行实现时,这个组件会显得过于臃肿。
- 如果项目简单可以不使用redux-thunk,数据请求在组件中完成。
- 当组件中有复杂的异步请求时,为了减少组件的复杂程度,把异步请求使用此中间件放在 actionCreator 集中管理。
js
import React, { Component } from 'react';
import actions from '../store/actions/thunk';
import { connect } from 'react-redux';
import css from '../styles/saga.scss';
/* @connect(
    state => state.thunk,
    actions
) */
class Thunk extends Component {
  constructor(props) {
    super(props);
  }
  /*   static getInitialProps(props) {
        console.log('数据仓库');
        console.log(props.store);
        console.log(props.store.getState());
        const { store } = props;
        const { topicTypes, topicLists, isFetching } = store.getState().thunk;
        return { topicTypes, topicLists, isFetching };
    } */
  handleSwitch = (e, key) => {
    this.props.fetchTopic(key);
  };
  handleFetchType = () => {
    this.props.fetchType();
  };
  render() {
    console.log('渲染了 ');
    console.log(this.props);
    const { topicTypes, topicLists, isFetching } = this.props;
    return (
      <div className={css.saga}>
        <button onClick={this.handleFetchType}>点我</button>
        <div className={css.topic}>
          <ul className={css.topictype}>
            {topicTypes.map((item, index) => (
              <li key={item.id} onClick={(e) => this.handleSwitch(e, item.id)}>
                {item.title}
              </li>
            ))}
          </ul>
          {isFetching ? (
            <div>加载中…</div>
          ) : (
            <ul className={css.topicList}>
              {topicLists.map((item, index) => (
                <li key={item.id}>
                  <a href={item.url}>{item.title}</a>
                </li>
              ))}
            </ul>
          )}
        </div>
      </div>
    );
  }
}
//  export default Thunk;
const mapStateToProps = (state) => {
  const { topicTypes, topicLists, isFetching } = state.thunk;
  return {
    topicTypes,
    topicLists,
    isFetching,
  };
};
const mapDispatchToProps = (dispatch) => ({
  fetchType: () => dispatch(actions.fetchType()),
  fetchTopic: (id) => dispatch(actions.fetchTopic(id)),
});
export default connect(mapStateToProps, mapDispatchToProps)(Thunk);
加入中间件
js
import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
const store = createStore(reducers, applyMiddleware(thunk));
redux-thunk 主要的功能就是可以让我们 dispatch 一个函数,而不只是普通的 Object。
js
//actions
import fetch from '../../services/api';
export const actionTypes = {
  REQUEST: 'REQUEST',
  TYPESUCCESS: 'TYPESUCCESS',
  TOPICSUCCESS: 'TOPICSUCCESS',
  ERROR: 'ERROR',
};
//reudx-thunk
const actions = {
  fetchType: () => async (dispatch) => {
    try {
      dispatch({ type: actionTypes.REQUEST });
      const { Data } = await fetch.topicType();
      dispatch({ type: actionTypes.TYPESUCCESS, payload: Data });
      await dispatch(actions.fetchTopic(Data[0].id));
    } catch (error) {
      dispatch({ type: actionTypes.ERROR, error });
    }
  },
  fetchTopic: (id) => async (dispatch) => {
    try {
      dispatch({ type: actionTypes.REQUEST });
      let { Data } = await fetch.topicList(id);
      dispatch({ type: actionTypes.TOPICSUCCESS, payload: Data });
    } catch (error) {
      dispatch({ type: actionTypes.ERROR, error });
    }
  },
};
export default actions;
redux-thunk 缺点:
 dispatch(action creator),但是函数内部极为复杂。如果需要为每一个异步操作都如此定义一个 action,显然 action 不易维护。