reactjs React Redux和本地存储

apeeds0o  于 2022-12-03  发布在  React
关注(0)|答案(1)|浏览(188)

我现在正在探索新的东西,开始学习React和还原。我有一个问题。
我知道如果我们想管理状态,那么我们使用useState钩子,但它在一个组件中,如果我们想访问其他组件中的状态,那么我们必须通过上下文API或useContext进行适当的钻取。Redux通过将状态保存为全局状态来解决这个问题,并且所有组件都可以访问存储。
我的第一个问题是如果我们通过浏览器url刷新页面,那么所有的redux都会被刷新。假设我们有一个欢迎页面,它在登录后显示给用户,我在这里应用了一些条件,如(向特定用户显示特定按钮),为了实现这一点,我们使用保存在redux存储中的状态应用了条件。如果用户通过url刷新页面,那么Redux存储中找不到变量,这会导致应用程序崩溃。在这种情况下该怎么办?
我的第二个问题是本地存储的实际用途是什么。我的意思是,如果我们在本地存储中保存redux存储或redux状态以避免应用崩溃,那么为什么在您实际将redux状态保存到本地存储时还需要redux呢?(那么为什么不只使用本地存储)。
我对这一切感到非常困惑。

46scxncf

46scxncf1#

为了回答你的第一个问题,我将使用一个例子。假设你的redux存储有3个键,appPhasedarkModesomeOtherState。它看起来像这样:

//store.js
import { configureStore } from "@reduxjs/toolkit";

const initialState = { appPhase: 'homePage', darkMode: false, someOtherState: "blah" };

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "UPDATE_PHASE": {
      return { ...state, appPhase: action.payload };
    }
    case "TOGGLE_DARK_MODE": {
      return { ...state, darkMode: action.payload };
    }
    case "UPDATE_SOME_OTHER_STATE": {
      return { ...state, someOtherState: action.payload };
    }
    default:
      return state;
  }
};

const configureAppStore = (preloadedState) => {
  const store = configureStore({
    reducer: reducer,
    preloadedState: preloadedState,
  });

  return store;
};

const store = configureAppStore(initialState);

export default store;

假设你的应用有四个appPhase,比如"homepage""browseProducts""shoppingCart""checkout"appPhase的initialState是"homepage"appPhase会随着用户使用你的应用而更新。在某个时候,用户处于"checkout"阶段,他们打开了darkMode,但是页面会刷新。并且这两个值返回到它们的初始状态{ appPhase: 'homePage', darkMode: false },则用户返回到主页并且他们必须再次打开darkMode。
这里可以使用localStorage来持久化这两个状态,这包括两个部分:编写一个中间件,将这两个状态存储在localStorage中,并使用持久化的状态对redux存储进行再水合。
您可以编写一个存储中间件来侦听"UPDATE_PHASE""TOGGLE_DARK_MODE"这两个操作,并且每当调度其中一个操作时,中间件都会获取该值并将其设置在localStorage中。
中间件可以类似于以下内容:

const localStorageMiddleware = ({ getState }) => {
    return (next) => (action) => {
      const result = next(action);
      if (action.type === 'UPDATE_PHASE') {
        localStorage.setItem(
          'applicationState',
          `{
              "appPhase": ${JSON.stringify(getState().appPhase)}
            }`
        );
      }
      if (action.type === 'TOGGLE_DARK_MODE') {
        localStorage.setItem(
          'applicationState',
          `{
              "darkMode": ${JSON.stringify(getState().darkMode)}
            }`
        );
      }

      return result;
    };
  };

现在,每当appPhasedarkMode发生变化时,我们不仅更新了存储,还在localStorage中进行了设置。
还有一个步骤,我们不会用我们在localStorage中持久化的状态来重新水合redux存储。如果我们要刷新,我们的存储仍然会反映我们的initialState,而不是我们在localStorage中持久化的值。
再水化方法如下所示:

const reHydrateStore = () => {
    let localstore;
    if (localStorage.getItem('applicationState')) {
      localstore = JSON.parse(localStorage.getItem('applicationState'));
    }
    // Merge InitialState with stuff in localstore
    return {...preloadedState, localstore};
  };

如果localStorage有applicationState,它将类似于{appPhase: "checkout", darkMode: true},它将把它合并到您的preloadedState中,而不会影响someOtherState(我们不想持久化的东西)。我们的再水合存储将反映我们的initialState和我们在localStorage中持久化的状态:

{ appPhase: 'checkout', darkMode: true, someOtherState: "blah" }

我们将通过configureStore()添加中间件和reHydrateStore方法,如下所示:

//store.js
import { configureStore } from "@reduxjs/toolkit";

const initialState = { appPhase: 'homePage', darkMode: false, someOtherState: "blah" };

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "UPDATE_PHASE": {
      return { ...state, appPhase: action.payload };
    }
    case "TOGGLE_DARK_MODE": {
      return { ...state, darkMode: action.payload };
    }
    case "UPDATE_SOME_OTHER_STATE": {
      return { ...state, someOtherState: action.payload };
    }
    default:
      return state;
  }
};

  const localStorageMiddleware = ({ getState }) => {
    return (next) => (action) => {
      const result = next(action);
      if (action.type === 'UPDATE_PHASE') {
        localStorage.setItem(
          'applicationState',
          `{
              "appPhase": ${JSON.stringify(getState().appPhase)}
            }`
        );
      }
      if (action.type === 'TOGGLE_DARK_MODE') {
        localStorage.setItem(
          'applicationState',
          `{
              "darkMode": ${JSON.stringify(getState().darkMode)}
            }`
        );
      }

      return result;
    };
  };

  const reHydrateStore = () => {
    let localstore;
    if (localStorage.getItem('applicationState')) {
      localstore = JSON.parse(localStorage.getItem('applicationState'));
    }
    // Merge InitialState with stuff in localstore
    return { ...preloadedState, localstore };
  };

  const store = configureStore({
    reducer: reducer,
    middleware: [localStorageMiddleware],
    preloadedState: reHydrateStore(),
  });

  return store;
};

const store = configureAppStore(initialState);

export default store;

还有redux-persist,它处理应用状态的持久化,并在web和移动的应用中对存储进行再水合。它提供了状态持久化之前的组件渲染延迟,以及要持久化的reducer的白名单和黑名单,等等。
至于你的第二个问题,“为什么要使用redux而不是localstorage”,我不知道我能不能正确地回答。它们经常结合使用,但我不确定是否将localStorage单独用作状态管理工具。
读/写redux存储要比阅读/写localStorage并在每次状态改变时解析json性能更高。您需要创造性地将localStorage更改分发到组件,而redux等工具正是为此而设计的。此外,客户端的任何人都可以使用开发人员控制台查看和修改localStorage中的数据。所以在localStorage中存储任何敏感的东西都可能会有问题。如果你对它们的区别感兴趣的话,你值得去谷歌一下。

相关问题