Redux拆分Reducer:如何构建预期的状态结构
如何正确拆分Redux Reducer以实现预期状态结构
首先明确你想要的最终状态结构:
state = { items: { currentItem: object, byId: object, allIds: array, fetching: bool }, someOtherModule: { ... } }
你之前尝试的两种方式都没达到预期,核心问题在于没有正确把拆分后的reducer直接映射到items对象的对应字段上。下面给你两种可行的解决方案:
方案一:拆分每个子reducer为单独文件
这是最清晰的拆分方式,每个状态字段对应一个独立的reducer文件:
准备单个子reducer文件:
items/reducers/currentItem.js(保留你原有的代码):const currentItem = (state = null, action) => { // 处理currentItem的action逻辑 } export default currentItem;items/reducers/byId.js:const byId = (state = {}, action) => { // 处理byId的action逻辑 } export default byId;items/reducers/allIds.js:const allIds = (state = [], action) => { // 处理allIds的action逻辑 } export default allIds;items/reducers/fetching.js:const fetching = (state = false, action) => { // 处理fetching状态的action逻辑 } export default fetching;
在
items/reducers/index.js中组合所有子reducer:
直接导入每个子reducer,通过combineReducers映射到items对象的对应字段:import { combineReducers } from 'redux'; import currentItem from './currentItem'; import byId from './byId'; import allIds from './allIds'; import fetching from './fetching'; export default combineReducers({ currentItem, byId, allIds, fetching });根reducer中导入组合好的
itemsreducer:import { combineReducers } from 'redux'; import items from './items/reducers'; import someOtherModule from './someOtherModule/reducers'; export default combineReducers({ items, someOtherModule });
这样就能完美得到你想要的状态结构,没有多余嵌套,每个字段对应独立的reducer逻辑。
方案二:合并部分子reducer到同一文件
如果不想拆分太多文件,可以把byId、allIds、fetching放在同一个文件导出,再在index.js中逐个导入组合:
items/reducers/items.js:export const byId = (state = {}, action) => { // 处理byId的逻辑 } export const allIds = (state = [], action) => { // 处理allIds的逻辑 } export const fetching = (state = false, action) => { // 处理fetching的逻辑 }items/reducers/index.js:
从items.js中解构出每个子reducer,再和currentItem一起组合:import { combineReducers } from 'redux'; import currentItem from './currentItem'; import { byId, allIds, fetching } from './items'; export default combineReducers({ currentItem, byId, allIds, fetching });根reducer写法和方案一完全一致,最终状态结构也符合预期。
为什么你之前的方式不行?
- 方式一和方式二中,你把包含
byId等的item对象直接传给combineReducers,但combineReducers要求每个值是单个reducer函数,而非对象,所以Redux不会展开这个对象,导致最终items下只有currentItem。 - 若在
items.js里先自行combineReducers({byId, allIds, fetching}),会把这三个字段包裹在额外的items嵌套中,不符合你的预期。
内容的提问来源于stack exchange,提问作者user210757
相关产品推荐
相关产品推荐

