几天来,我一直在努力从本地存储加载Map
。在action reducer中创建了一个Map
,并成功地将其序列化并保存到本地存储中。在刷新时加载(标志rehydrate
被设置为true
)会出现问题。Map
似乎已成功反序列化,但在@ngrx/store/init
操作后(仅在刷新后),它并不以新状态存在,而是只有{}
(空对象)。我还想知道为什么在第一次初始化(页面加载;本地存储为空)之后是null
(这是正确的),而在其他初始化(刷新)之后则是{}
。
我也试过replacer
和reviver
的功能
- replacer:JSON.stringify文档中指定的replacer函数
- reviver:在JSON.parse文档中指定的reviver函数
但没有成功。
我创建了Stacklitz项目。
感谢您的帮助。
问题的原因是默认用于恢复数据的deepmerge包不支持Map and Set
为了修复它,你需要
- 用深度合并ts替换深度合并
- 将
mergeReducer
添加到ngrx-store-localstorage
配置
这是更新的演示
import { deepmerge } from "deepmerge-ts";
const INIT_ACTION = '@ngrx/store/init';
const UPDATE_ACTION = '@ngrx/store/update-reducers';
export function localStorageSyncReducer(
reducer: ActionReducer<any>
): ActionReducer<any> {
return localStorageSync({
keys: [
{
map: {
serialize: (map) => Array.from(map.entries()),
deserialize: (map) => new Map(map),
},
},
],
rehydrate: true,
mergeReducer(state, rehydratedState, action) {
if ((action.type === INIT_ACTION || action.type === UPDATE_ACTION) && rehydratedState) {
state = deepmerge(state, rehydratedState);
}
return state;
},
removeOnUndefined: true,
restoreDates: true,
})(reducer);
}
我自己试过了,我看到了同样的东西
奇怪的是,github上没有关于这方面的问题。所以我不确定这是一个变通办法还是一个解决方案。
在文档中,您可以看到:
mergeReducer(可选)(状态:任意,再水合状态:任意、操作:任意)=>any:定义用于将存储中的重新水合状态与ngrx存储中的状态合并的还原器。如果未指定,则默认对INIT_ACTION或UPDATE_ACTION执行完全深度合并。
因此rehydratedState
被解析为一个分离的状态,然后与原始状态合并。也许这就是为什么我们总是看到{}
——合并状态的原因。
为了克服这一点,我宣布mergeReducer直接返回再水合状态
return localStorageSync({
keys: [
...
],
...
mergeReducer: (state: any, rehydratedState: any, action: any) => {
return rehydratedState;
}
})(reducer);
我想,对于更多的自定义状态值,您还需要在这个函数中自己合并它。