Redux - 如何从 localStorage 部分填充 initialState

时间:2021-02-10 12:34:51

标签: javascript reactjs redux redux-toolkit

我在我的应用程序中使用 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));
        }
      }
    }
  }
});

0 个答案:

没有答案