web-dev-qa-db-ja.com

React Redux:レデューサーにロジックが含まれている必要があります

追加、更新、削除のケースを備えたカート削減機能があります。 reduxストア内にも製品配列があります。商品配列に2つのアイテムが追加された場合、2つのアイテムではなく、数量の値を増やします。私の主な質問は、レデューサーにロジックが含まれている場合、つまり、製品の配列に正確な製品がすでに含まれているかどうかを判断し、製品の数量に関する更新を返すか、この動作をプレゼンテーションコンポーネント内で処理して既存の製品をチェックし、新しい製品を追加するかです。製品または数量の更新?

function CartReducer (state = initialState, action) {
  switch (action.type) {
    case AddToCart:
      return {
        ...state,
        products: [...state.products, action.product],
        totalPrice: state.totalPrice += (action.price * action.quantity)
      }

    case RemoveItemCart:

      return {
        ...state,
        products: [
          ...state.products.slice(0, action.index),
          ...state.products.slice(action.index + 1)
        ]
      }

    case UpdateItemQuantity:
      return {
        ...state,
        products: state.products.map((product, index) => {
          if (index === action.index) {
            return Object.assign({}, product, {
              quantity: action.quantity
            })
          }
          return product
        })
      }

    default:
      return state
  }
}
21
IVI

ごと The Redux FAQレデューサーとアクション作成者の間のロジックの分割に関するエントリ

リデューサーまたはアクションクリエーターでどのロジックを実行する必要があるかについて、明確な答えは1つではありません。一部の開発者は、アクションのデータを取得して対応する状態に盲目的にマージする「シン」レデューサーを使用して、「ファット」アクションクリエーターを持つことを好みます。他の人たちは、アクションをできるだけ小さく保つことを強調し、アクションクリエーターでのgetState()の使用を最小限に抑えようとします。 (この質問の目的のために、sagasやオブザーバブルなどの他の非同期アプローチは「アクションクリエーター」カテゴリに分類されます。)

レデューサーにロジックを追加すると、いくつかの潜在的なメリットがあります。アクションタイプは、より意味があり、より意味のあるものになる可能性があります(「SET_STATE」ではなく「USER_UPDATED」など)。さらに、レデューサーのロジックが多いほど、タイムトラベルデバッグの影響を受ける機能が多くなります。

このコメントは二分法をうまくまとめています:

さて、問題は、アクションクリエーターに何を入れ、リデューサーに何を入れるか、脂肪と薄いアクションオブジェクトの間の選択です。すべてのロジックをアクションクリエーターに配置すると、基本的に状態の更新を宣言するファットアクションオブジェクトが作成されます。レデューサーは純粋で、無意味で、追加され、削除され、これらの関数が更新されます。簡単に作成できます。しかし、ビジネスロジックの多くは存在しません。レデューサーにロジックを追加すると、データロジックのほとんどが1か所にまとめられた素敵なシンアクションオブジェクトになりますが、他のブランチからの情報が必要になる可能性があるため、レデューサーを構成するのが難しくなります。あなたは大きなレデューサー、または州の上位から追加の引数を取るレデューサーで終わることになります。

私も書きました 「厚くて薄い」減速機についての私自身の考え

アクションクリエーターにロジックを追加することと、レデューサーにロジックを追加することには、妥当なトレードオフがあります。最近見た良い点の1つは、レデューサーのロジックが多いほど、タイムトラベルデバッグの場合に再実行できるものが多くなることです(これは一般的に良いことです)。

個人的には、両方の場所にロジックを一度に配置する傾向があります。アクションをディスパッチする必要があるかどうか、ディスパッチする場合はその内容を決定するのに時間をかけるアクションクリエーターを作成します。ただし、アクションの内容を確認し、それに応じて複雑な状態の更新を実行する、対応するレデューサーも作成することがよくあります。

11
markerikson

間違いなく!レデューサーは純粋な関数でなければならないため、ロジックも純粋でなければなりません。これは、副作用がないことを意味します。副作用には以下が含まれます(ただし、これらに限定されません)。

  • データベースのリクエスト/ストア
  • ファイルIO
  • REST /非同期呼び出し
  • グローバルまたは外部の変異
  • あらゆる種類のデータ変異

したがって、レデューサーは、入ってくる状態を決して変更してはなりませんが、変更があった場合にのみ、そのコピーに変更を加えたコピーを返します。不変値(文字列、数値、未定義な​​ど)はそのまま返され、変更されていない場合は状態を返すことができます。ただし、入力に変更を加える必要がある場合は、新しいコピーまたは新しい値を返します。

レデューサーから呼び出されるロジックに関しては、そのすべてのコードがこれらの要件を満たしている限り、Reduxパターンと一致しています。

残念ながら、JavaScriptには、特定のコードに副作用がある(他の言語がそうである)かどうかを確実に知る方法がないため、呼び出している内容に注意する必要があります。

あなたが失敗した場合、それはReduxを壊しますか?いいえ。しかし、あなた(またはFlux/Redux開発者)が期待するとおりに動作しない場合があります。

3
Brian Genisio

ミドルウェアで何をしたいかを検討してください...すべてのロジックをレデューサー内に配置すると、ミドルウェアのレコードにビジネスロジックが適用されなくなります。

  1. dispatch(new UpdatePerson(person))
  2. ミドルウェアを実行し、UpdatePersonアクションをインターセプトする
  3. レデューサー-人の年齢の値を更新します

たとえば、レコードをストアに保存すると、レデューサーロジックの実行が遅くなり、ミドルウェアで必要な状態の変更されたレコードにアクセスできなくなります。

0
orangesherbert

いいえ、ロジックを含めることはできません


  • Components:アクションの依存関係として既存のreduxデータを渡す必要があります
  • アクション:できるだけ多くのデータを収集し、できるだけ多くのレデューサーに適用可能
  • Reducers:保存するアクションオブジェクトの一部を抽出します
  • * Side Effects:後続のアクションリスナー/ディスパッチャ。最初のイベントを発行する前に待機したくない場合に便利です(サーガはサブスクリプションベースで、サンクは宣言チェーンです)。

経験則として、すべてをできるだけ熱心に行うことです

熱心な操作(早期復帰、フェイルファースト、巻き上げ状態など)により、特定の依存関係が同時に存在するかどうかが明確になり、簡単な決定が可能になります

熱心な操作は、「懸念の分離」と、モジュール式、宣言的、ステートフル、実用的、読みやすいコードのシンプルなテーマに沿っています:依存関係を宣言し、操作し、返す

それ以外はすべてシーケンスの問題であり、できるだけ熱心に行う必要があります

レデューサーは、何でも「実行」したい最後の場所です。実質的には「リターン」であり、アクションオブジェクトからデータを選択するだけです。

0
neaumusic