Redux Reducer深层数据被覆盖问题求助
解决Redux Reducer中深层对象数据被覆盖的问题
嘿,我看你遇到了Redux reducer里深层嵌套对象数据被覆盖的问题——每次接口返回数据后,之前的分类和日期数据都丢了,最后只留下最后一次请求的结果。这其实是因为你在更新嵌套对象时,没有正确保留每一层已有的数据,而是直接替换了对应层级的对象。
问题根源分析
看你当前的Reducer代码:
case FETCH_SINGLE_RESULT: return {...state, [action.meta.year]: {...state[action.meta.year], [action.meta.venue]: {...state[action.meta.venue], [action.meta.category]: {...state[action.meta.category], [action.meta.day]: action.payload.data}}}};
这里的问题在于,当你访问state[action.meta.venue]或者state[action.meta.category]时,如果当前state里还没有对应的键(比如第一次处理cat1时),会得到undefined,用...undefined展开相当于什么都没加;就算已有对应键,你也只替换了该分类下的对象,没有保留该分类下已有的其他日期数据——比如处理cat1的day2时,直接覆盖了cat1对象,导致之前的day1数据丢失。
解决方案:逐层兜底合并已有数据
要解决这个问题,我们需要每一层都先获取已有的数据(没有就用空对象兜底),再用扩展运算符合并新数据,确保每一层的已有内容都不会被覆盖。
修改后的Reducer代码如下:
case FETCH_SINGLE_RESULT: // 逐层获取已有数据,不存在则用空对象兜底 const currentYearData = state[action.meta.year] || {}; const currentVenueData = currentYearData[action.meta.venue] || {}; const currentCategoryData = currentVenueData[action.meta.category] || {}; // 逐层构建新状态,确保每一层都合并已有数据 return { ...state, [action.meta.year]: { ...currentYearData, [action.meta.venue]: { ...currentVenueData, [action.meta.category]: { ...currentCategoryData, // 保留该分类下已有的所有日期 [action.meta.day]: action.payload.data // 新增/更新当前日期的数据 } } } };
为什么这样有效?
- 每一步我们都先拿到对应层级已有的数据,比如
currentCategoryData会包含该分类下已经请求到的所有日期数据; - 用
...currentCategoryData展开后,再添加当前的[action.meta.day]字段,这样就不会覆盖之前的日期数据; - 所有层级都遵循这个逻辑,就能保证年份、场地、分类下的所有数据都被正确保留和追加。
进阶优化:用Immer简化嵌套更新
如果你的项目嵌套层级很深,手动写多层扩展运算符会很繁琐,可以用Immer库来简化不可变更新的写法。Immer允许你用“可变”的写法修改状态,它会自动帮你生成不可变的新状态。
安装Immer后,Reducer可以改成这样:
import produce from 'immer'; // ...其他代码 case FETCH_SINGLE_RESULT: return produce(state, draft => { // 自动兜底创建空对象,不用手动判断 draft[action.meta.year] = draft[action.meta.year] || {}; draft[action.meta.year][action.meta.venue] = draft[action.meta.year][action.meta.venue] || {}; draft[action.meta.year][action.meta.venue][action.meta.category] = draft[action.meta.year][action.meta.venue][action.meta.category] || {}; // 直接赋值,Immer会处理不可变更新 draft[action.meta.year][action.meta.venue][action.meta.category][action.meta.day] = action.payload.data; });
这种写法更直观,也不容易出错,特别适合处理复杂的嵌套状态结构。
内容的提问来源于stack exchange,提问作者moto
相关产品推荐
相关产品推荐

