【问题标题】:How To Update Structure of Redux State Persisted In LocalStorage如何更新 LocalStorage 中持久化的 Redux 状态结构
【发布时间】:2019-05-12 17:13:36
【问题描述】:

我将一部分 Redux 状态保存在 localStorage 中,以便在页面刷新时保持它。

如果我的 Redux 状态结构发生变化,如何更新 localStorage 中的状态结构?


示例:

这是我的 combineReducer 文件:

// combineReducer

const rootReducer = combineReducers({
  usersPage: usersPageReducer,
  form: formReducer
})

我的 usersPageReducer 中的原始默认状态如下所示:

// usersPageReducer.js

defaultUsersPageState = {
  selectedColumns: ["name", "email"],    
}

我使用以下方法加载并保存到 localStorage:

// localStorage.js

export const loadState = () => {
  try {
    const serializedState = localStorage.getItem('state')
    if (serializedState === null) {
      return undefined;
    }
    return JSON.parse(serializedState)
  } catch (err) {
    return undefined
  }
}

export const saveState = (state) => {
  try {
    const serializedState = JSON.stringify(state)
    localStorage.setItem('state', serializedState)
  } catch (err) {
    // to define
  }
}

在我的主文件中,我订阅了商店,并保存了状态的usersPage 切片。我使用来自 localStorage 的初始状态创建商店:

// main.js
const persistedState = loadState();
const initialState = { ...persistedState };

const store = createStore(
  rootReducer,
  initialState,
);

store.subscribe(() => {
  saveState({
    usersPage: store.getState().usersPage
  })
})

现在假设我想更改我的 usersPageReducer 默认状态,以便它也跟踪排序。

// usersPageReducer.js

defaultUsersPageState = {
  selectedColumns: ["name", "email"],
  sorting: {"name": "asc"}   
}

上述方法不起作用,因为在应用程序启动时,我们从 localStorage 中对 redux 初始状态进行了水合。旧的初始状态击败了 usersPageReducer defaultUsersPageState

由于 localStorage 不知道 usersPageReducersorting 键,并且我们从不使用默认状态,因此 sorting 键永远不会添加到 redux 状态。

有没有办法对 redux 存储进行水合,以便它使用默认状态初始化每个 reducer(好像我们没有使用 localStorage),然后传播存储的状态?

【问题讨论】:

  • 您可以通过将默认状态与缓存状态深度合并来创建初始状态。这样做会将新值添加到旧的缓存状态。
  • 我将在哪里进行合并?我是否必须将每个减速器的默认状态导入我的main.js 文件?在这种情况下,将defaultUsersPageState 导入main.js?这似乎无法在我的大型应用程序中扩展。

标签: javascript reactjs redux react-redux local-storage


【解决方案1】:

两个可能的解决方案我可以建议你:-

1. 使用变量来跟踪应用程序的版本(更好的是 redux-version )。现在,每当更改此变量的值时,您的应用程序将清除用户的 LocalStorage 并使用 defaultUsersPageState 提供的全新的 redux 结构(或其子部分),而不是而不是从中加载可用的(陈旧的)数据。

你可以通过多种方式实现这一点,我的是

// localStorage.js

export const loadState = (CurrVersion) => {
  try {
    // check if version matches or not ... 
    // for first time localStorage.getItem('appVersion') will be null
    if (CurrVersion !== localStorage.getItem('appVersion')){
      localStorage.removeItem('state') // 
       // update the appVersion in LS with current version
      localStorage.setItem('appVersion', CurrVersion) 
      return undefined;
    }
    else{
      const serializedState = localStorage.getItem('state')
      if (serializedState === null) {
         return undefined;
       }
       return JSON.parse(serializedState)
      }
   } catch (err) {
      return undefined
  }
}

main.js

// change it whenever breaking changes are added and it makes sense 
const CurrVersion = 'MY-APP-VERSION-2.0' 
const persistedState = loadState(CurrVersion);
const initialState = { ...persistedState };

const store = createStore(
  rootReducer,
  initialState,
);

store.subscribe(() => {
  saveState({
    usersPage: store.getState().usersPage
  })
})

  1. 明确检查持久化数据的结构是否更改。如果更改,您可以删除以前的对象并使用已更新结构的默认初始状态。但请记住,此检查需要递归地(或深度地)完成,您可能会发现 lodash 对此很有用。

P.S:如果你有大项目,请使用为这个问题构建的 npm 包,例如 react-persist

【讨论】:

    猜你喜欢
    • 2018-05-21
    • 2022-11-11
    • 2021-05-20
    • 1970-01-01
    • 2018-06-22
    • 1970-01-01
    • 2019-05-30
    • 2020-12-25
    • 2019-03-11
    相关资源
    最近更新 更多