この質問のようなユースケースを考えると:
関連する状態フィールドを分割レデューサーで更新する最良の方法は?
自分の状態の外にある状態に依存するレデューサーのアクションを処理するためのベスト プラクティスは何ですか? 上記の質問の作成者は、状態ツリー全体を 3 番目の引数としてすべてのレデューサーに渡すだけになりました。これは手荒で危険なようです。Redux FAQ には、次の潜在的な解決策がリストされています。
- レデューサーが状態の別のスライスからのデータを知る必要がある場合、1 つのレデューサーがより多くのデータを処理できるように、状態ツリーの形状を再編成する必要がある場合があります。
- これらのアクションの一部を処理するために、いくつかのカスタム関数を作成する必要がある場合があります。これには、combineReducers を独自の最上位レデューサー関数に置き換える必要がある場合があります。
- reduce-reducers などのユーティリティを使用して、combineReducers を実行してほとんどのアクションを処理することもできますが、状態スライスにまたがる特定のアクションに対してより特化したレデューサーを実行することもできます。
- redux-thunk などの非同期アクション作成者は、getState() を介して状態全体にアクセスできます。アクション作成者は、状態から追加のデータを取得してアクションに入れることができるため、各レデューサーは自身の状態スライスを更新するのに十分な情報を持ちます。
私のユースケースでは、複数フォーム/複数ステップのプロセスでユーザーが移動できるページを決定するアクション「続行」があります。これはアプリの状態全体に大きく依存するため、できません。私の子レデューサーのいずれかでそれを処理します。今のところ、ストアをアクション クリエーターに引き込みました。ストアの現在の状態を使用して、アクティブなページを変更する「ページ」リデューサーを起動するアクション オブジェクトを計算します。おそらく redux-thunk をインストールし、このアクション クリエーターで getState() を使用しますが、まだこのアプローチにはコミットしていません。
この方法で処理する必要があるアクションは (これまでのところ) 1 つしかないため、これはそれほど悪い解決策ではないと思います。より良い解決策があるかどうか、状態とレデューサーを再構築して簡単にする方法があるかどうか、または私がやっていることは Redux のベストプラクティスの範囲内であるかどうか疑問に思っています。似たような例があれば、それも役に立ちます。
もう少しコンテキストを与えるために、現在の状態ツリーは次のようになっています。
{
order: order.result,
items: order.entities.items,
activePage: {
id: 'fulfillment'
// page info
},
pagesById: { // all the possible pages
fulfillment: {
id: 'fulfillment'
// page info
}
}
}
アクティブなページは、ユーザーが次のページに進むためにデータを入力する必要があるページ/セクションです)。アクティブなページの決定は、ほとんどの場合、アイテムの状態に依存し、注文の状態に依存する場合もあります。最終結果は、ユーザーがいくつかのフォームに連続して入力し、フォームが有効になったら続行を押すアプリです。続行すると、アプリは必要な次のページを判断して表示します。
編集:子レデューサーと組み合わせて「グローバル」レデューサーを実装するアプローチを試しました。
実装はこんな感じ…
const global = (currentState = initialState, action) => {
switch (action.type) {
default:
return currentState
}
}
const subReducers = combineReducers({
order,
meta
})
export default function (currentState = initialState, action) {
var nextState = global(currentState, action)
return subReducers(nextState, action)
}
グローバル レデューサーは最初にアプリ全体の状態で実行され、その結果が子レデューサーに渡されます。状態のさまざまな部分を読み取るためだけに、アクション クリエーターに大量のロジックを追加する必要がなくなったという事実が気に入っています。
すべてのアクションがすべてのレデューサーにヒットし、レデューサーが呼び出される順序は常に同じであるため、これは redux の原則に沿っていると思います。この実装について何か考えはありますか?
編集: 現在、ページの状態を処理するためにルーター ライブラリを使用しているため、activePage と pagesById はなくなりました。