Chrome运行React应用触发Redux状态突变报错,仅当前标签刷新复现
问题根因分析
- 报错核心是Redux检测到了非法的状态突变,该突变由Chrome扩展导致:部分Chrome扩展(如你提到的Google Sheet扩展)会在页面加载时自动向页面上下文内的身份认证相关对象注入自定义属性,你应用的oidc用户信息直接存储在Redux store中,扩展注入的
randomItem属性相当于在Redux两次dispatch之间直接修改了store内的oidc.user.profile.amr对象,因此触发了Redux的不可变性检测规则。 - 仅Chrome出现报错的原因:不同浏览器的扩展运行权限逻辑不同,Chrome扩展的内容脚本默认拥有更高权限修改页面上下文内的对象,Firefox对扩展修改页面全局对象的限制更严格,因此不会触发该问题。
- 仅当前标签页重载报错、新标签页正常的原因:Chrome扩展的注入时机和标签页缓存状态相关,当前标签页重载时扩展会复用之前的上下文注入逻辑,优先将自定义属性注入到已有的缓存对象上;新开标签页时页面所有对象都是全新初始化的,扩展注入时机晚于Redux store初始化oidc用户信息的时机,不会触发两次dispatch之间的突变检测。
解决方案
方案1:OIDC用户信息存入Redux时做深拷贝+冻结
在将oidc返回的用户信息写入Redux store前,先做一次完整的深拷贝,还可以通过Object.freeze把嵌套对象全部冻结,阻止外部扩展修改:
// 在处理oidc用户信息的reducer逻辑中修改 const user = oidcClient.getUser(); // 深拷贝后再存入store,若用户信息含函数/循环引用,可替换为structuredClone() const clonedUser = JSON.parse(JSON.stringify(user)); // 可选:冻结对象防止外部修改 const frozenUser = deepFreeze(clonedUser); dispatch(setOidcUser(frozenUser));
方案2:关闭指定路径的Redux状态突变检测(推荐开发环境用)
如果仅本地开发环境遇到该问题,不需要修改业务逻辑,直接在Redux store配置中忽略指定路径的突变检测即可:
// store配置文件 export const store = configureStore({ reducer: rootReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ immutableCheck: { // 忽略oidc相关路径的突变检测 ignoredPaths: ['oidc.user.profile.amr'], }, serializableCheck: { ignoredPaths: ['oidc.user'], }, }), });
方案3:调整oidc用户信息的存储位置
如果oidc用户信息不需要参与Redux的状态更新流程,可以直接存储在全局变量或者React Context中,避开Redux的不可变性检测,扩展修改对象也不会触发报错。
验证方法
修改完成后开启触发报错的Chrome扩展,多次按下F5刷新页面,确认不会再触发突变报错即可。
内容的提问来源于stack exchange,提问作者Bardelman
相关产品推荐
相关产品推荐

