如何在React中使用useReducer钩子+上下文管理状态的同时合并化简器

时间:2019-10-15 22:35:18

标签: reactjs react-hooks react-context

我正在构建状态有些复杂的应用程序。所以我决定使用带有上下文API的React UseReducer挂钩来管理我的状态 这是我个人的减速器:

UserReducer:

import { actionTypes } from '../actions/user';

const userInitialState = {
  navItems: []
};

const userReducer = (state = userInitialState, action = '') => {
  switch (action.type) {
    case actionTypes.CHANGE_NAVITEMS:
      return {
        ...state,
        navItems: action.data
      };
    default:
      return state;
  }
};

export default userReducer;

Nav Reducer:

import { actionTypes } from '../actions/nav';

const navInitialState = {
  isLoaded: false,
  submenuStates: []
};

const navReducer = (state = navInitialState, action = '') => {
  switch (action.type) {
    case actionTypes.CHANGE_SUBMENUSTATES:
      return {
        ...state,
        submenuStates: action.data
      };
    case actionTypes.CHANGE_ISLOADED:
      return {
        ...state,
        isLoaded: action.data
      };
    default:
      return state;
  }
};

export default navReducer;

Spinner Reducer:

import { actionTypes } from '../actions/spinner';

const spinnerInitialState = {
  isLoading: false
};

const spinnerReducer = (state = spinnerInitialState, action = '') => {
  switch (action.type) {
    case actionTypes.CHANGE_ISLOADING:
      return {
        ...state.nav,
        submenuStates: action.data
      };
    default:
      return state;
  }
};

export default spinnerReducer;

这是我目前结合减速器的尝试:

import navReducer from './nav';
import spinnerReducer from './spinner';
import userReducer from './user';

const reducers = ({ data, ui } = {}, action) => {
  if (!data || !ui) {
    return {
      data: {
        user: userReducer()
      },
      ui: {
        nav: navReducer(),
        spinner: spinnerReducer()
      }
    };
  }

  return {
    data: {
      user: userReducer(data.user, action)
    },
    ui: {
      nav: navReducer(ui.nav, action),
      spinner: spinnerReducer(ui.spinner, action)
    }
  };
};

const initialState = reducers();
export { reducers, initialState };

您可能会说,我遇到了“无法设置尝试尝试该行的未定义错误的属性用户

user: userReducer(data.user, action)

所以我求助于上面的if语句。基本上,如果未定义data或ui,则此代码首先调用不带参数的reducer单个函数,以便它们退回到默认值,从而创建一个空状态对象。

我发现这种模式非常丑陋且重复。在我不重复自己的情况下,有没有一种更清洁的方法?

0 个答案:

没有答案