如何在刷新时保留redux状态树?

时间:2016-05-12 19:13:00

标签: reactjs redux flux

Redux文档的第一个原则是:

  

整个应用程序的状态存储在单个商店的对象树中。

我实际上认为我理解所有校长。 但我现在很困惑应用意味着什么。

如果应用程序只是网站中一个复杂的部分,只能在一个页面中工作,我理解。但如果申请意味着整个网站怎么办?我应该使用LocalStorage或cookie或其他东西来保存状态树吗?但是如果浏览器不支持LocalStorage怎么办?

我想知道开发人员如何保留他们的状态树! :)

4 个答案:

答案 0 :(得分:63)

虽然提供的答案在某些时候有效但重要的是要注意redux-storage软件包已被弃用且不再维护...

  

包redux-storage的原作者决定弃用该项目,不再维护。

现在,如果您不希望依赖其他软件包以避免将来出现类似问题,那么很容易推出自己的解决方案。

您需要做的就是:

1-创建一个函数,从localStorage返回状态,然后将状态传递给第二个参数中的createStore的redux函数,以便为商店提供水合作用

 const store = createStore(appReducers, state);

2-监听状态更改,每次状态更改时,将状态保存到localStorage

store.subscribe(() => {
    //this is just a function that saves state to localStorage
    saveState(store.getState());
}); 

那就是......我实际上在制作中使用了类似的东西,但是我没有使用函数,而是编写了一个非常简单的类,如下所示......

class StateLoader {

    loadState() {
        try {
            let serializedState = localStorage.getItem("http://contoso.com:state");

            if (serializedState === null) {
                return this.initializeState();
            }

            return JSON.parse(serializedState);
        }
        catch (err) {
            return this.initializeState();
        }
    }

    saveState(state) {
        try {
            let serializedState = JSON.stringify(state);
            localStorage.setItem("http://contoso.com:state", serializedState);

        }
        catch (err) {
        }
    }

    initializeState() {
        return {
              //state object
            }
        };
    }
}

然后引导您的应用...

import StateLoader from "./state.loader"

const stateLoader = new StateLoader();

let store = createStore(appReducers, stateLoader.loadState());

store.subscribe(() => {
    stateLoader.saveState(store.getState());
});

希望它有助于某人

演出说明

如果应用程序中的状态更改非常频繁,过于频繁地保存到本地存储可能会损害应用程序的性能,尤其是在序列化/反序列化的状态对象图很大的情况下。对于这些情况,您可能希望使用RxJslodash或类似的东西去抖动或限制将状态保存到localStorage的函数。

答案 1 :(得分:43)

如果您希望在浏览器刷新期间保持redux状态,最好使用redux中间件执行此操作。查看redux-persistredux-storage中间件。他们都试图完成存储redux状态的相同任务,以便随意保存和加载。

答案 2 :(得分:0)

这是基于Leo的答案(应该是公认的答案,因为它无需使用任何第三方库即可实现问题的目的。

我创建了一个Singleton类,该类创建Redux商店,使用本地存储对其进行持久化,并允许通过吸气剂轻松访问其商店

要使用它,只需在主类中放置以下Redux-Provider元素:

// ... Your other imports
import PersistedStore from "./PersistedStore";

ReactDOM.render(
  <Provider store={PersistedStore.getDefaultStore().store}>
    <MainClass />
  </Provider>,
  document.getElementById('root')
);

并将以下类添加到您的项目中:

import {
  createStore
} from "redux";

import rootReducer from './RootReducer'

const LOCAL_STORAGE_NAME = "localData";

class PersistedStore {

  // Singleton property
  static DefaultStore = null;

  // Accessor to the default instance of this class
  static getDefaultStore() {
    if (PersistedStore.DefaultStore === null) {
      PersistedStore.DefaultStore = new PersistedStore();
    }

    return PersistedStore.DefaultStore;
  }

  // Redux store
  _store = null;

  // When class instance is used, initialize the store
  constructor() {
    this.initStore()
  }

  // Initialization of Redux Store
  initStore() {
    this._store = createStore(rootReducer, PersistedStore.loadState());
    this._store.subscribe(() => {
      PersistedStore.saveState(this._store.getState());
    });
  }

  // Getter to access the Redux store
  get store() {
    return this._store;
  }

  // Loading persisted state from localStorage, no need to access
  // this method from the outside
  static loadState() {
    try {
      let serializedState = localStorage.getItem(LOCAL_STORAGE_NAME);

      if (serializedState === null) {
        return PersistedStore.initialState();
      }

      return JSON.parse(serializedState);
    } catch (err) {
      return PersistedStore.initialState();
    }
  }

  // Saving persisted state to localStorage every time something
  // changes in the Redux Store (This happens because of the subscribe() 
  // in the initStore-method). No need to access this method from the outside
  static saveState(state) {
    try {
      let serializedState = JSON.stringify(state);
      localStorage.setItem(LOCAL_STORAGE_NAME, serializedState);
    } catch (err) {}
  }

  // Return whatever you want your initial state to be
  static initialState() {
    return {};
  }
}

export default PersistedStore;

答案 3 :(得分:-2)

最初的问题是

  

我想知道开发人员如何保留他们的状态树! :)

好吧,因为我没有看到这个答案,你确实使用了React标签;通常,React webapps实现为SPA(单页应用程序),不会真正刷新浏览器。他们可能会通过更改您在地址栏中看到的URL来使看起来像一样。一种流行的方法是react-router

但是,SPA状态仍然无法在浏览器刷新后继续存在,因此就是redux-persist进入时。