我在我的应用程序中使用 redux-toolkit 来管理商店。所以,我有以下状态模型;
RootState {
teams: {
teamBySomeId: {}
virtualTeamById: {}
}
}
我正在尝试同步商店和 localStorage
。 但是,我只想同步 virtualTeamById
。因此,保存到localStorage
中的状态如下;
teamsVirtualState: '{teams: {virtualTeamById: {"50": "Some data"}}}'
当我在启动时将 localStorage
值加载到应用程序时,一切运行正常,并且 preloadedState
填充了上面的内容。
现在,我有以下用于所述状态的选择器,如下所示;
export const teamByIdSelector = (id: number) => (state: RootState): ITeam => state.teams.teamBySomeId[id];
export const virtualTeamByIdSelector = (id: number) => (state: RootState): IVirtualTeam => state.teams.virtualTeamById[id];
这是它错误的地方!似乎 redux 期望 teamBySomeId
存在,并且通过恢复上面部分的状态,我已经改变了teams
状态对象成为不同的模型。
这是 typescript 在 teamByIdSelector 上返回的错误;
<块引用>类型错误:无法读取未定义的属性“176”
关于我们应该如何管理 localStorage
和 redux store 之间的同步进程,有什么首选方法吗?还是我总是需要将整个商店对象保存到 localStorage
中?
感谢任何建议。
同步机制代码;
/**
* @description Mapping relation between synchronous mechanism between redux store and localStorage
* @description Format is { storageKey: storePath }
* @summary Add more field if there is more thing to sync store between the app and client
*
* @field storageKey The key that will be used to save the store into localStorage
* @field storePath The path where the store object is located
*/
const storeStorageMap: { [storageKey: string]: string } = {
"teamsVirtualTeam": "teams.virtualTeamById"
};
export const createStore = (initialState: any = {}, localStorage?: boolean) => {
if (localStorage && window && window.localStorage) {
const storageState: { [key: string]: any } = {};
/** Loads value from localStorage */
for (const storageKey in storeStorageMap) {
if (Object.prototype.hasOwnProperty.call(storeStorageMap, storageKey)) {
const storePath = storeStorageMap[storageKey],
rawValue = window.localStorage.getItem(storageKey);
if (storePath && rawValue) {
try {
const jsonValue = JSON.parse(rawValue);
_.set(storageState, storePath, jsonValue);
}
catch(err) {
break;
}
}
}
}
/** Extends initialState with storageState */
initialState = _.merge(initialState, storageState);
}
console.log({initialState});
return configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}).concat(logger),
devTools: process.env.NODE_ENV !== 'production',
preloadedState: initialState || {},
});
};
const store = createStore({}, true);
/**
* Subscribe to event whenever dispatch is being called
*/
store.subscribe(() => {
const combinedState = store.getState();
console.log({combinedState});
/**
* Persists value of virtualTeamById to localStorage
*/
if (window && window.localStorage) {
for (const storageKey in storeStorageMap) {
if (Object.prototype.hasOwnProperty.call(storeStorageMap, storageKey)) {
const storePath = storeStorageMap[storageKey],
storeValue = _.get(combinedState, storePath);
if (storeValue && !_.isEmpty(storeValue)) {
window.localStorage.setItem(storageKey, JSON.stringify(storeValue));
}
}
}
}
});