web-dev-qa-db-ja.com

Reduxの状態とURLクエリパラメーターを同期する方法

検索パネルのあるWebページがあります。検索パネルにはいくつかの入力フィールドがあります:id、size、...

ユーザーが検索値(例:id = 123およびsize = 45)を設定し、検索ボタンを押すときが欲しい

  1. reduxレデューサーのsearchStateは、新しい検索値(id = 123およびsize = 45)で更新する必要があります
  2. URLは「 http:// mydomain/home?id = 123&size = 45 」に変更する必要があります

一方、ユーザーがURLを http:// mydomain/home?id = 111&size = 22 に変更した場合:

  1. レデューサーのsearchStateは、新しい検索値(id = 111およびsize = 22)で変更する必要があります
  2. UI検索パネルの入力は、新しい値(id = 111およびsize = 22)で更新する必要があります

目標を達成する方法は?どのルーターを使用する必要がありますか(react-router、redux-router、react-router-reduxまたはその他)。

61
Anton

React Router を直接使用し、notReduxでsearchStateを保持することをお勧めします。 ReactルーターはコンポーネントにURLパラメーターを挿入し、mapStateToProps(state, ownProps)でそれらを使用して最終的な小道具を計算できます。

ルートの変更をアクションとして本当に見たい場合は、双方向同期に react-router-redux を使用できますが、状態のパラメーターは提供されず、現在の場所だけが提供されます。アクションを記録および再生し、再生時にURLバーを更新する場合の唯一のユースケースです。

決して必要ではありません。ほとんどの場合、Reactルーターを直接使用するだけで十分です。

51
Dan Abramov

要するにredux-query-sync を使用して、ストア内のURLパラメーターとフィールドの同期を維持できます。ルーターなしで動作します。


より長いストーリー:同じ質問に苦労し、ダン・アブラモフの answer をまず評価し、(私の言葉では) 「セカンドストア」としてのURL、Reduxストア外のアプリケーション状態の一部。しかし、その後、2種類の「ストア」があると、コードを変更するのが難しくなることがわかりました。各「ストア」には異なるインターフェイスがあるため、物事を一方から他方に移動します。開発者として、Redux状態のフィールドのいずれかを選択し、URLでexposeを選択し、場所が私の州(の一部)への小さな窓。

したがって、状態から値を選択するセレクター関数を提供できるようにredux-query-syncを公開しました。この関数は、指定したパラメーター名のウィンドウの場所に表示されます。また、URLからRedux状態(たとえば、アプリケーションが最初にロードされるとき)に他の方向で同期できるようにするには、パラメーター値を渡すアクションクリエーターを提供して、レデューサーがそれに応じて状態を更新できるようにします。

12
Gerben

私が最初のシナリオを処理してきた方法は次のとおりです。

  • 入力値が変更されると、そのコンポーネントは、コンテナからプロップとして渡されたコールバックをトリガーします。

  • コールバックでは、コンテナはイベントが発生したときにRedux状態を更新するアクションをディスパッチします。

  • アクション呼び出しの直後の行では、this.context.router.Push()を使用し、正しいクエリ文字列でURLを渡します。

これが正しいアプローチであるかどうかはわかりません。私の意見では、クエリ文字列はそのマスターではなく状態を反映する必要があるため、最初にURLを更新する方が望ましいと思いました。

逆のシナリオに関しては、私には本当にわかりません。 URLを手動で設定すると、完全なリロードがトリガーされるように見えますが、間違っている可能性があります。

使用するルーターについては、Reactルーターを単独で使用しています。私は他の人を使うことに本当に価値を見いだしていませんでした この議論 は私にとって決定的でした。

2
cantera

私は最近、これと同様の問題の作業を終了しました。ストアとしてMobXを使用し、ルーターとしてredux-routerを使用しました。 (react-routerでうまくいきましたが、コンポーネントの外部にプッシュアクションをディスパッチする必要がありました-グローバルストアとしてのreduxはここでうまく機能します)

私の解決策は、カンテラが説明したものに似ています-私のルーターの状態は、フォームの状態を単に反映したものです。これには、フォームの状態を捨てる必要がなく、ルーターの状態に完全に依存するという追加のボーナスがあります。


最初のシナリオでは、

1)通常どおりフォーム入力を更新します。これにより、結果コンポーネントで再レンダリングがトリガーされます。

2)結果コンポーネントのcomponentDidUpdate()では、フォームの小道具を使用して更新されたクエリ文字列を作成します。

3)更新されたクエリ文字列をルーター状態にプッシュします。これは、純粋にURLを更新するためのものです。


2番目のシナリオの場合

1)ルートonEnterコンポーネントのRouteフックで、使用可能なクエリ文字列を取得し、それを初期フォーム値に解析します。

2)値でストアを更新します。これは、ページの最初のロード、およびルーターの状態がフォームの状態を決定する唯一の場合のみです。


編集:このソリューションでは、URLが状態を更新しないため、ブラウザーの履歴に戻る場合は考慮されません。

2
xiankai

新しいツール react-url-query をお勧めします。これにより、同期が非常に簡単になります。

1
Hearen