【问题标题】:Redux-Actions handleActions Nested ReducersRedux-Actions handleActions 嵌套化简器
【发布时间】:2018-03-21 06:07:10
【问题描述】:

也许我遗漏了一些非常明显的东西,但今天这让我很头疼。

假设我们有一个结构如下的 Redux 存储:

const state = {
  ...
  pages: {
    ...
    accountPage: {
      currentTab: 'dashboard',
      fetching: false,
      tableSettings: {
        sortDir: 'asc',
        sortField: 'name'
      }
    }
  }
}

那么显然有一个主reducer...

export default combineReducers({
  ...
  pages: pagesReducer
  ...
});

那么pages的reducer对每个页面都有reducer...

export default combineReducers({
  ...
  accountPage: accountPageReducer
  ...
});

现在我们终于进入了问题的核心,这个特定状态的 reducer。

export default handleActions({
   [setCurrentTab]: (state, action) => { ... },
   [setIsFetching]: (state, action) => { ... }
});

没关系吧?好吧,一开始在tableSettings 给出的状态键实际上应该由它自己的reducer 处理。这种模式在 state 中可能存在很多次,因此被抽象为一个 reducer-creating 函数:

const defaultState = {
  sortDir: 'asc',
  sortField: null
};

export const createTableSettingReducer (actions, extra ={}) => {
  return handleActions({
    [actions.changeSortDir]: (state, action) => ({ ...state, sortDir: action.payload }),
    [actions.changeSortField]: (state, action) => ({ ...state, sortField: action.payload }),
    ...extra
  }, defaultState)
}

因此,在状态部分 (accountPageReducer) 的减速器之上,我们创建了减速器:

// pretend these actions were imported
const tableSettingsReducer = createTableSettingReducer({
  changeSortDir: setSortDir,
  changeSortField: setSortField
});

所以问题是,我把tableSettingsReducer放在哪里?

这当然行不通:

export default handleActions({
   [setCurrentTab]: (state, action) => { ... },
   [setIsFetching]: (state, action) => { ... },
   tableSettings: tableSettingsReducer
});

它不起作用,因为handleActions 期望使用动作常量作为键,而不是状态中的实际键。

也没有地方可以使用combineReducers,因为这个状态片只有一个嵌套的reducer。 currentTabfetching不需要自己的reducer,所以用combineReducers是徒劳的。

我知道最近 redux-actions 开始支持嵌套减速器...但实际上并没有任何可用的文档准确说明它应该如何完成,甚至没有描述实现它所需的参数。

我可以使用combineActions,并将handleActions 中的所有操作组合起来,用于嵌套reducer 可以执行的每个操作。但这似乎不是很干净......另外,如果嵌套减速器有它自己的嵌套减速器怎么办?这意味着每次这些 reducer 可以处理一个新动作时,都需要将该动作添加到其所有父级中的combineActions。不是最好的。

想法?

【问题讨论】:

    标签: redux nested reducers redux-actions


    【解决方案1】:

    您所在州的每个键都有自己的 reducer。有些 reducer 非常简单,有些是由其他 reducer 组成的。状态树每一级的所有姊妹键都可以与combineReducers 组合。

        const initialCurrentTab = 'dashboard';
        const currentTabReducer = handleActions({
           [setCurrentTab]: (state, action) => {
             return action.payload;
           },
        }, initialCurrentTab);
    
        const defaultFetchingState = false;
        const fetchingReducer = handleActions({
           [setIsFetching]: (state, action) => {
             return action.payload;
           },
        }, defaultFetchingState);
    
        export default combineReducers({
          currentTab: currentTabReducer,
          fetching: fetchingReducer,
          tableSettings: tableSettingsReducer,
        });
    

    【讨论】:

      【解决方案2】:
      let say you have the initialState = { data : []}
        let assume that the upcoming action has payload of an array 
      export the reducer as the following :
      
       return  handleActions({
             ["Action Type 1" ]: (state, { payload }) => {
              return { ...state, data:  [...state.data, ...payload ]} ;
             },
             ["Action Type 1" ]: (state, { payload }) => {
               return { ...state, data:  [...state.data, ...payload ]} ;
             },
          }, initialSate );
      
          import this reducer in your combine reducer .
      

      【讨论】:

        猜你喜欢
        • 2015-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多