Redux Persist配合RTK Query清除浏览器数据后rehydrate报错
报错原因
手动清空浏览器存储后,Redux Persist 触发REHYDRATE动作时,本地无任何持久化数据,此时action.payload值为undefined。现有extractRehydrationInfo逻辑未做存在性校验,直接读取action.payload[reducerPath],触发读取undefined属性的类型错误,导致RTK Query状态水合流程中断。
修复方法
修改notesApi中的extractRehydrationInfo配置,增加层级判断:当action.payload不存在、或payload中无对应reducer路径的缓存数据时,直接返回undefined即可。RTK Query识别到返回值为undefined时,会自动跳过本次水合,使用内置初始状态,不会抛出异常。
修改后的配置代码:
extractRehydrationInfo(action, { reducerPath }) { if (action.type === REHYDRATE && action.payload) { return action.payload[reducerPath] } },
如果项目支持ES2020可选链语法,也可以简写为:
extractRehydrationInfo(action, { reducerPath }) { if (action.type === REHYDRATE) { return action.payload?.[reducerPath] } },
额外可选优化
- 默认配置下Redux Persist会持久化整个root reducer下的所有状态,RTK Query的接口缓存数据通常不需要长期持久化,可在
persistConfig中增加黑名单配置,排除API缓存状态,减少持久化数据体积:
const persistConfig = { key: "root", storage, blacklist: [notesApi.reducerPath] // 排除RTK Query缓存 };
如果确实需要持久化接口缓存,保留原有配置即可,仅添加前面的存在性判断就可以解决清空存储后的报错问题。
prepareHeaders中读取token的逻辑也存在同类风险,当状态未完成水合时userInfo可能为undefined,建议增加可选链判断避免后续报错:
prepareHeaders: (headers, { getState }) => { const token = getState().userReducer.userInfo?.token; if (token) { headers.set("authorization", `Bearer ${token}`); } return headers; },
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

