也许我遗漏了一些完全明显的东西,但这让我今天感到不安。
假设我们有一个 Redux 存储,其结构如下:
const state = {
...
pages: {
...
accountPage: {
currentTab: 'dashboard',
fetching: false,
tableSettings: {
sortDir: 'asc',
sortField: 'name'
}
}
}
}
所以显然有一个主减速器...
export default combineReducers({
...
pages: pagesReducer
...
});
然后页面的减速器有每个页面的减速器......
export default combineReducers({
...
accountPage: accountPageReducer
...
});
现在我们终于来到了问题的核心,这个特定状态的减速器。
export default handleActions({
[setCurrentTab]: (state, action) => { ... },
[setIsFetching]: (state, action) => { ... }
});
这一切都很好,对吧?好吧,一开始给出的 state 中的 keytableSettings
实际上应该由它自己的 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)
}
因此,在 state ( accountPageReducer
) 部分的 reducer 之上,我们创建了 reducer:
// 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。currentTab
并且fetching
不需要自己的reducer,所以使用是没有结果的combineReducers
。
我知道最近redux-actions
开始支持嵌套减速器......但实际上没有任何可用的文档准确显示它应该如何完成,甚至描述实现它所需的参数。
我可以使用combineActions
, 并将所有操作组合handleActions
到嵌套减速器可以执行的每个操作中。但这似乎不是很干净......另外,如果嵌套减速器有它自己的嵌套减速器怎么办?这意味着每次这些 reducer 可以处理一个新动作时,都需要将该动作添加到combineActions
其所有父级中。不是最好的。
想法?