Reduxドキュメントの最初のプリンシパルは次のとおりです。
アプリケーション全体の状態は、単一のストア内のオブジェクトツリーに保存されます。
そして、私は実際にすべての校長をよく理解していると思いました。しかし、私は今、アプリケーションが何を意味するのか混乱しています。
アプリケーションがウェブサイトの小さな複雑な部分の1つを意味し、1ページだけで機能する場合、私は理解しています。しかし、アプリケーションがウェブサイト全体を意味する場合はどうでしょうか?状態ツリーを保持するために、LocalStorageまたはCookieなどを使用する必要がありますか?しかし、ブラウザがLocalStorageをサポートしていない場合はどうなりますか?
開発者が状態ツリーをどのように保持しているかを知りたい! :)
ブラウザの更新後もredux状態を維持したい場合は、reduxミドルウェアを使用してこれを行うのが最善です。 redux-persist および redux-storage ミドルウェアを確認してください。両方とも、redux状態を保存するという同じタスクを実行して、自由に保存およびロードできるようにします。
-
編集
私がこの質問を再訪してからしばらく経ちましたが、もう一方(より賛成の答えですが)があなた自身のソリューションの展開を奨励しているのを見て、私はこれにもう一度答えると思いました。
この編集の時点で、両方のライブラリは過去6か月以内に更新されています。私のチームは数年前から本番環境でredux-persistを使用しており、問題はありませんでした。
単純な問題のように思えるかもしれませんが、独自のソリューションを導入すると、メンテナンスの負担が生じるだけでなく、バグやパフォーマンスの問題が発生することがすぐにわかります。最初に思い浮かぶ例は次のとおりです。
JSON.stringify
およびJSON.parse
は、不要な場合にパフォーマンスを低下させるだけでなく、reduxストアなどの重要なコードで処理しないとアプリケーションをクラッシュさせる可能性があるエラーをスローする可能性があります。まとめると、 2.5kB縮小+ gzip圧縮済み これは問題ではないので、自分のチームに自分で解決するよう依頼します。
コメントの1つで述べたように。元の redux-storage パッケージは react-stack に移動しました。このアプローチは、独自の状態管理ソリューションの実装に引き続き焦点を当てています。
提供された答えはある時点で有効でしたが、元の redux-storage パッケージが廃止され、メンテナンスされていないことに注意することが重要です...
パッケージredux-storageの元の作成者は、プロジェクトを廃止することを決定し、メンテナンスされなくなりました。
将来、これらのような問題を回避するために他のパッケージに依存したくない場合は、独自のソリューションを簡単に展開できます。
あなたがする必要があるのは:
1- localStorage
から状態を返す関数を作成し、ストアをハイドレイトするために、2番目のパラメーターで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());
});
それが誰かを助けることを願っています
アプリケーションで状態の変更が非常に頻繁に行われる場合、特にシリアライズ/デシリアライズする状態オブジェクトグラフが大きい場合、ローカルストレージへの保存が頻繁に行われると、アプリケーションのパフォーマンスが低下する可能性があります。これらの場合、RxJs
、lodash
、または同様のものを使用して、状態をlocalStorageに保存する関数をデバウンスまたはスロットルすることができます。
これは、Leoの回答に基づいています(サードパーティのライブラリを使用せずに質問の目的を達成するため、これは受け入れられた回答である必要があります)。
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;