web-dev-qa-db-ja.com

ウィンドウのリロード時にRedux状態がリセットされる(クライアント側)

非常に大きくネストされた情報を持つオブジェクトと配列のように、userInfo、chatInfoなどの非常に大きく複雑なオブジェクトがあります。事は私のページを更新するたびに私の反応アプリにありますredux状態はリセットされ、それらすべてのAPIを再度呼び出す必要があります。

私はこのトピックについていくつかの研究をしました。 Reduxに関するDan Abramovのeggheadチュートリアルを確認しました。彼が行うことは、ブラウザーのlocalStorageのredux状態を維持し、100または500ミリ秒ごとにlocalStorageを更新することです。これはコードのにおいのようです。

LocalStorageの状態を継続的に監視して更新すると、ブラウザーのパフォーマンスに影響しませんか。 Angular 1は、状態変数を継続的に監視し続けたために失敗し、しばらくするとサイトがブラウザーでライブ状態に保たれた場合、速度が低下しました。スクリプトは変数の状態を継続的にチェックし続けているので、ここでも同じことをしているように感じます。

LocalStorageでredux状態を維持することが正しいアプローチである場合、誰かがその理由を教えてもらえますか?そして、そうでない場合、より良いアプローチはありますか?


これは複製ではありません 更新時にredux状態ツリーを永続化するにはどうすればよいですか? ローカルストレージでの状態の永続化がコードの匂いであるかどうかのアドバイスを求めているため

15
Adeel Imran

localStorageを使用するのがここでの最良のオプションだと思います。そこに格納しているデータはクライアントで必要とされるからです。データが変更されていない場合は、localStorageを繰り返しクエリしたり監視したりする必要はありません。

もう1つのことは、localStorageclosure で囲むことです。これにより、「大きな」データを取得するときに常にディスクにヒットするわけではありません。すべてのブラウザーはlocalStorageを異なる方法で実装するため、一貫した動作またはI/Oパフォーマンスの保証はありません。

これにより、実装を非表示にし、ユーザーデータに関連するすべてを1か所で制御する抽象化の単純なレイヤーも追加されます。

これは、ユーザープロファイルデータクロージャの簡単な例です。

_// UserProfile.js
var UserProfile = (function() {
  var userData = {};

  var getUserData = function() {
    if (!userData) { 
      userData = JSON.parse(localStorage.getItem("userData"));
    }
    return userData;
  };

  var setUserData = function(userData) {
    localStorage.setItem("userData", JSON.stringify(userData));
    userData = JSON.parse(localStorage.getItem("userData"));
  };

  return {
    getUserData: getUserData,
    setUserData: setUserData
  }
})();

export default UserProfile;
_

ユーザーデータオブジェクトを設定します。これにより、localStorageが上書きされ、ローカル変数がクロージャー内に設定されます。

_import UserProfile from '/UserProfile';
UserProfile.setUserData(newUserData);
_

ユーザーデータオブジェクトを取得します:これは、クロージャー内のローカル変数からデータを取得するか、またはlocalStorageから取得します設定されていません。

_import UserProfile from '/UserProfile';
var userData = UserProfile.getUserData();
_

ここでの考え方は、最初にlocalStorageから、アプリが読み込まれるとき、または最初のAPI呼び出しで、データをメモリに読み込むことです。ユーザープロファイルデータが変更される(つまり、ユーザーがプロファイルを更新するなど)までは、APIを再度クエリし、UserProfile.setUserData(..)呼び出しを介してデータを再度更新します。

6
grizzthedj

問題は、どの時点で持続性を達成する必要があるかです。私はあなたの場合の答えはページのリロードにあると感じています。したがって、パフォーマンスが心配な場合は、次のようにします。*状態が変化したときにのみlocalStorageを更新します。状態を更新するときのレデューサーの内部。 *アプリの起動時にlocalStorageから読み取ります。

(この方法では、状態が変化したときにのみ書き込み、一度だけ読み取ります)

追伸Reduxアプリで永続性を実現するには、 https://github.com/rt2zz/redux-persist パッケージをお勧めします。

6
Krasimir

私はこれを弱いキャッシュとしてのみ実行し、それに依存しません。ローカルストレージは制限されており(Chromeなど)5MB)、使用できない場合があります。データが書き込まれたことを慎重に確認する必要があります。

他の人が言ったように、あなたは定期的にストアをフラッシュしているlocalStorageを見ていません。しかし、すべての状態がローカルストレージに保持するのに適切であると盲目的に仮定するのは、かなり大まかなハックのように思われることに同意します。すべてのキャッシングソリューションと同様に、影響(鮮度、有効期限など)を慎重に検討する必要があります。これを段階的に実行したいようです。キャッシュに適した、ぶらさがっていない果物をいくつか選び、その状態をローカルストレージにキャッシュすることの影響を考慮してください。

5
john_omalley

redux-persisを試してみてください。基礎となるプラットフォーム(Web /モバイル)にとらわれず、楽観的な永続性を実行できます。

それでもパフォーマンスがボトルネックになる場合。次のいずれかの手順を実行できます。

キャッシュミドルウェア

変更をリッスンして記録するミドルウェアを作成しますが、5秒ごとにのみフラッシュします。

イベントハンドラーをwindow.beforeunloadにアタッチして、ユーザーがナビゲートしたり、ブラウザーを閉じて変更をフラッシュしたりすることを検出します

持続性戦略

データを永続化するには、以下の2つの戦略のいずれかを使用できます。

  • パフォーマンスのボトルネックがない場合は、localStorageに保管してください。
  • ファイルのアップロードのようにサーバーにJSONブロブを送信します。アプリが読み込まれてローカルに永続化するときに、最後のJSON状態を取得します。

redux-persistの使用から始めることをお勧めします。それでもパフォーマンスのボトルネックがある場合は、2つの永続化戦略のいずれかとともにキャッシュミドルウェアを使用します。

4
Muhammad Adeel

ほとんどの場合、特定のアクションが発生した後もlocalStorageに状態を保持する必要があると思います。少なくとも私がそれを持続させる必要があったプロジェクトでは常にそうでした。

したがって、副作用を調整するためにredux-sagaredux-observable、またはredux-cyclesを使用している場合は、簡単にその副作用(状態をlocalStorageに永続化する)を発生させることができますそれらのアクションの1つが行われるときはいつでも。これは、時間間隔に基づいてデータを「ランダムに」永続化するよりもはるかに優れたアプローチだと思います。

2
Josep

状態の監視についてのあなたの理解は、あなたの状態をチェックし、localStorageでそれを更新し続けるある種の間隔があるということです。ただし、reactライフサイクルメソッドcomponentDidUpdateでlocalStorageを更新することで、同じことを実現できると思います。このメソッドはコンポーネントが更新されるたびに起動するので、このメソッドを利用して、パフォーマンスに影響を与えることなく、起動するたびにlocalStorageを更新できます。

2
Chaim Friedman

大規模なredux + reactアプリケーションで状態を保持することは完全に問題ありません。

Angular1については、ウォッチャーとダイジェストサイクルは、rehydrate状態であってもすべての状態が変化しても、rexux接続APIとvrtualDOMの反応のために、すべてのコンポーネントがレンダリングされるわけではありません。

確認してもいい:

パフォーマンスはあなたの主な関心事ではありません。それがあなたの状態を正規化し、ドラフトなどの重要な情報のみを保持する場合(少ない情報-水分補給が少ない)。

この種のセットアップの大きな問題は、通常、アプリにバックグラウンド同期またはソケットの更新がある場合です。ブラウザの複数のタブがあると、ローカルDBへの非同期書き込みが発生し、以前の状態で上書きされます。

クロスタブ同期のためのその上に薄いラッパーがあります redux-persist-crosstab

これらの実装のいくつかをmattermost webappで確認し、リアルタイムアプリでどのように使用するかを確認できます。

安定性とパフォーマンスを高めるためにいくつかのフープを通過します- ストアファイルへのリンク ほとんどのWebアプリケーションで

2
Sudheer

1つのオプションはINITIAL_STATEにデータをロードすることです

window.__INITIAL_STATE__ = { ...state... }

そしてレデューサーをロードします:

window.__APP_STATE__.__REDUCERS__.Push(reducer) 
2
Chandan

redux-storage というnpmモジュールを使用できると思います。 柔軟なバックエンドを備えたreduxの永続層を提供します。 redux-storageを任意の redux-storage-engine と組み合わせることができます。そして、私の見解では、これを redux-storage-engine-sessionstorage と組み合わせることができ、ブラウザーが開かれるまで情報を共有して保存するだけであると想定します。 localStorageでブラウザを膨らませる必要はありません。これを明確にするには、追加のJavaScriptサポートが必要です。

Redux-storageは、状態が変化するたびにロードおよび保存アクションをトリガーします。ロードおよび保存の場合に何をすべきかについてのすべてのより多くの柔軟性を提供します。また、状態の変更を保存しない場合は、除外する状態の配列を定義します。

1
cauchy