当我们的应用随着业务的发展,变得越来越复杂的时候,组件之间的状态也是越来越复杂。

reducer函数

之前说过redux中的action,是用来描述一种变化。但是完成变化并且生辰新的数据数据状态的是reducer方法。

reducer方法,必须是纯函数,才能保证数据变化的可预测性。也就是说执行每一步变化,我们都可以预测数据的结果。比如:

export default function menuReducer(
  state = {
    menuState,
    isCollapse: false,
  },
  action: any
) {
  switch (action.type) {
    case types.MENU_COLLAPSES:
      return {
        ...state,
        isCollapse: action.payload,
      };
    default:
      return { ...state };
  }
}

这reducer函数,是控制菜单的收缩状态的,它对应的action,我是这样写的:

import * as types from "@/store/types";

export const changeCollapse = (isCollapse: boolean) =>({
  type: types.MENU_COLLAPSES,
  payload: isCollapse,
});

效果如下图:

Redux的纯函数、中间件_react


按钮组件的代码如下:

import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons";
import { connect } from "react-redux";
import { changeCollapse } from "@/store/redux/menu/action";

const CollapsesIcon = (props: any) => {
  const { isCollapses, changeCollapse } = props;
  return (
    <div
      className="collapsed"
      onClick={() => {
        changeCollapse(!isCollapses)
      }}
    >
      {isCollapses ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
    </div>
  );
};
const mapStateToProps = (state: any) => {
  return { isCollapses: state.menus.isCollapse };
};
const mapDispatchToProps = { changeCollapse };
export default connect(mapStateToProps, mapDispatchToProps)(CollapsesIcon);

在一个应用中,我们不可能使用一个action来描述所有的变化,这样不利于维护。一般情况是一个action描述一种变化,同时也会定义对应的reducer函数。

redux提供了一个工具函数combineReducers,来合并所有的reducer函数。比如:

import { combineReducers } from "redux";
import menuReducer from "../redux/menu/menu";
import globalReducer from "../redux/global/reducer";
import { auth } from "../redux/auth";
const reducers = combineReducers({
    menus: menuReducer,
    global:globalReducer,
    auth
});

export default reducers

combineReducers函数接收一个Object类型的参数,这个参数包含了页面的数据状态、已经状态数据和reducer函数之间的映射关系。

这就是redux的纯函数reducer。

中间件

redux中间件就是在派发action和执行reducer之间,添加一些自定义的功能。

比如记录日志、调用异步接口或者路由等等。

Redux的纯函数、中间件_redux_02


redux是通过applyMiddleware方法来接入中间件的,比如:

let store = legacy_createStore(configStore, composeEnhancers(
  applyMiddleware(...middleware, reduxPromise)
));

比如现在在开发环境中,想记录一下状态数据变化的日志,可以使用redux-logger:

import { createLogger } from 'redux-logger';
const logger = createLogger();
store = legacy_createStore(configStore, composeEnhancers(
  applyMiddleware(...middleware, reduxPromise,logger)
));

这样就是轻松的查看状态数据的变化记录,效果如图:

Redux的纯函数、中间件_数据_03


但是,需要留意一下,redux-logger需要放在所有中间件的最后面,才能准确打印日志哦。