使用redux-persist时返回undefined而非默认redux state如何解决
问题根因
你使用redux-persist-transform-filter默认配置时,写入持久化存储阶段只会保留你指定的filters/sideFilters/queryParam字段,状态恢复(rehydrate)阶段默认会直接用持久化返回的仅包含过滤字段的对象,替换对应reducer的完整状态,导致你原本在reducer里定义的其他字段(比如示例中的subscriptionCardInformation、isSubscriptionCardInformationLoading)全部丢失变成undefined,这就是触发报错的核心原因。
最优解决方案
方案1:配置自动状态合并(改动最小,优先选择)
redux-persist 官方自带了状态合并策略,你只需要在persistConfig里新增stateReconciler配置即可,实现持久化字段和初始状态的自动合并:
// 首先引入官方合并策略 import { autoMergeLevel2 } from 'redux-persist/lib/stateReconciler/autoMergeLevel2' const persistConfig = { key: 'root', storage, whitelist: [ // 保持你的原有白名单配置不变 'user', 'dashboard', // ...其余字段 ], transforms: [ // 保持你的原有transforms配置不变 subscriptionsFilter, rebillingFilter, // ...其余filter ], // 新增合并策略配置 stateReconciler: autoMergeLevel2 }
autoMergeLevel2会做两层浅合并:根级的reducer模块不会被替换,每个模块下持久化存储的字段(比如subscriptions下的filters)会覆盖初始状态的对应字段,其余初始定义的字段会全部保留,不会变成undefined。
方案2:调整过滤规则,仅过滤写入操作
你可以调整createFilter的参数,只在写入持久化存储时做字段过滤,状态读出时不过滤,避免额外的字段丢失:
// 原写法默认读写都做过滤,修改为第三个参数传null,即出站(读出)不过滤 const subscriptionsFilter = createFilter('subscriptions', ['filters'], null); const rebillingFilter = createFilter('subscriptionsRebillingStatistics', ['filters'], null); // 其余所有createFilter都按这个规则修改即可
该方案可以和方案1配合使用,进一步降低字段丢失的概率。
方案3:完善reducer初始状态
检查所有加入白名单的reducer,明确定义所有用到的字段的初始值:
// 示例:subscriptions reducer的初始状态 const initialState = { filters: {}, subscriptionCardInformation: null, isSubscriptionCardInformationLoading: false, // 其他所有用到的字段都预先定义默认值 }
哪怕极端情况出现状态合并异常,也不会出现字段为undefined的情况。
完成以上配置后,你就可以去掉组件里的|| {} fallback逻辑了。
内容的提问来源于stack exchange,提问作者Nemus

