【问题标题】:Reusing actions across multiple reducers in redux在 redux 中跨多个 reducer 重用操作
【发布时间】:2016-12-15 16:52:26
【问题描述】:

所以我正在开发一个大型的 react/redux 应用程序,并且对它在 redux 中管理状态的简单性感到非常满意。我们对 reducers/action/action Creators 使用“鸭子”风格的方法来保持事物相对基于域。此外,我们尝试保持 ui 状态与域相关联,并且大多数 reducer 具有类似的结构。它看起来像这样:

export default function home(state = initialState, action = {}) {
  switch (action.type) {
    case OPEN:
      return {
        ...state,
        ui: {
          ...state.ui,
          [action.key]: true
        }
      };
    case CLOSE:
      return {
        ...state,
        ui: {
          ...state.ui,
          [action.key]: false
        }
      };
    case SELECT_TAB:
      return {
        ...state,
        ui: {
          selectedTab: action.selected
        }
      };
    default:
      return state;
  }
}

我们最终会在 ui 上一遍又一遍地重复相同的操作,主要是切换和设置显示的内容。有没有办法将基于域的 ui 保留在 reducer 中,而不必在每个 reducer 中为 ui 添加 OPENCLOSE 类型语句。也许我在想的是 redux 中的一种反模式,但很想知道是否有人以前遇到过这种问题?

更新:

我喜欢下面列出的解决方案,但是您将如何扩展减速器以在其中包含一个 ui 减速器。

combineReducers({ 
    home: {createUiReducer('home', initialState), ...home}
})

这样您就可以拥有基于域的嵌套用户界面,而无需重复所有操作。不知道你会怎么做,因为你基本上会动态添加 CASE 语句。

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    你需要用前缀来命名它们。如果您像大多数开发人员一样懒惰,那么创建一个辅助函数来为您生成减速器;)

    喜欢这个..

    const createOpenCloseReducer = (prefix, initialState) => {
      const = ui = prefix + "_UI";
    
      return (state = initialState, action) => {
         switch(action.type) {
         case (prefix + "_CLOSE"):  
           return { ...state, [ui]: "CLOSED" }
         case (prefix + "_OPEN"):
           return { ...state, [ui]: "OPENED" }
         default: 
           return state
         }
      }
    }
    
    import { combineReducers, createStore } from 'redux';
    
    const rootReducer = combineReducers({
       home: combineReducers({
          ui: createOpenCloseReducer("HOME", { "HOME_UI": "CLOSED" }),
          data: someOtherHomeDataReducer
       }),
       someOther: createOpenCloseReducer("OTHER", { "OTHER_UI": "CLOSED" })
    })
    
    store = createStore(rootReducer)
    
    // use it..
    store.dispatch({type: "HOME_CLOSE"})
    store.dispatch({type: "OTHER_OPEN"})
    
    // your state..
    store.getState().home.ui // {HOME_UI: "CLOSED"}
    store.getState().someOther // {OTHER_UI: "OPENED"}
    

    【讨论】:

    • 感谢您的回复,但是我已经将每个操作命名为 const OPEN = 'if-planning/home/OPEN'; 之类的命名空间,我想即使我有一个具有一组默认 ui 操作的辅助函数,我也不太明白。我应该把它放在原来的减速器里面吗?
    • 如此接近,但并不能完全解决在家庭减速器中进行其他操作的问题,请查看我想要实现的编辑。
    • @PhilipChmalts 您可以多次使用 combineReducers 并为您的商店构建一棵树,而不仅仅是一个平面对象..
    • 谢谢!我知道尝试保持商店相对平坦很重要,但我喜欢将 ui 与域保持一致。这应该有助于减少臃肿!
    • 如果它对您的领域有好处,为什么不......人们正在这样做,它一点也不坏。祝你有美好的一天
    猜你喜欢
    • 1970-01-01
    • 2017-10-03
    • 2020-09-12
    • 2019-09-03
    • 2018-08-12
    • 2023-03-03
    • 1970-01-01
    • 2016-05-30
    • 1970-01-01
    相关资源
    最近更新 更多