javascript 如何更新本地存储中持久化的Redux状态的结构

xpcnnkqh  于 2023-02-18  发布在  Java
关注(0)|答案(2)|浏览(111)

我将Redux状态的一部分保存在localStorage中,以便可以在页面刷新时保持它。
如果我的Redux状态结构发生了变化,我如何更新localStorage中的状态结构?
示例:
这是我的combineReducer文件:

// combineReducer

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

My 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一样),然后扩展存储的状态?

d6kp6zgx

d6kp6zgx1#

有 * 两个 * 可能 * 解决 * 我可以建议你:-

**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对此很有用。
如果你有大的项目,使用为这个问题构建的npm包,例如react-persist

oxiaedzo

oxiaedzo2#

可以使用hash方法来实现这一点。
计算应用程序加载时初始redux密钥的哈希值,并将其存储在浏览器的本地存储中
现在计算应用程序中redux密钥的哈希值,并将其与浏览器本地存储中的哈希值进行比较。
如果它们都匹配,则不需要执行任何操作;如果不匹配,则注销它们或更新本地存储中的当前redux存储
sha256散列可用于实现此目的
示例

import { sha256 } from "js-sha256";
const hash = sha256(digest);

输入

{"auth":"{\"email\":null,\"token\":null,\"error\":null,\"loading\":false,\"authRedirectPath\":\"/dashboard\",\"role\":null,\"clientId\":null,\"registerMessage\":null,\"signupCreds\":{}}

输出

29e9cceee4e2df4c53d134dedd0d171939caaab412b17332b3d864693dc62780

相关问题