Redux-Actions handleActions嵌套的Reducers

时间:2017-10-09 23:29:04

标签: redux nested reducers redux-actions

也许我错过了一些完全明显的东西,但今天这让我感到沮丧。

假设我们有一个Redux商店,结构如下:

    loadApiCoins({ commit }) {
        Vue.axios({
            method: 'get',
            url: 'https://api.coinmarketcap.com/v1/ticker/',
            headers: {
                'Authorization': '',
            },
        }).then(...)
    },

所以显然有一个主要的减速器......

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

然后页面的reducer有每页的reducer ...

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

现在我们终于明白了问题的关键,这个特定州的减速器。

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

这一切都很好吗?好吧,在export default handleActions({ [setCurrentTab]: (state, action) => { ... }, [setIsFetching]: (state, action) => { ... } }); 开始时给出的状态中的键实际上应该由它自己的reducer处理。这种模式可能在状态中存在很多次,因此它被抽象为reducer创建函数:

tableSettings

因此,在状态部分(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) } )的reducer之上,我们创建了reducer:

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,因为这个状态片只有一个嵌套的reducer。 combineReducerscurrentTab不需要自己的reducer,因此使用fetching毫无结果。

我知道最近combineReducers开始支持嵌套的Reducer ...但是实际上没有任何文档可以显示它应该如何完成,甚至描述实现它所需的参数。

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

思想?

2 个答案:

答案 0 :(得分:2)

处于状态的每个键都有其自己的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,
    });

答案 1 :(得分:0)

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 .