web-dev-qa-db-fra.com

React Redux: Les réducteurs doivent-ils contenir une logique quelconque

J'ai une fonction de réduction de panier avec ajout, mise à jour et suppression de cas. J'ai également une gamme de produits dans le magasin Redux. Lorsque deux éléments sont ajoutés au tableau de produits, au lieu d’avoir deux éléments, j’incrémente la valeur de la quantité. Ma principale question est de savoir si les réducteurs doivent contenir une logique, c'est-à-dire déterminer si le tableau de produits contient déjà le produit exact et ne renvoie qu'une mise à jour sur la quantité de produit ou si ce comportement doit être géré dans le composant de présentation vérifiant les produits existants et ajoutant un nouveau produit ou mise à jour de la quantité?

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
  }
}
7
Murat Sert

Per l'entrée Redux FAQ sur la logique de scission entre réducteurs et créateurs d'action :

Il n’existe pas de réponse claire et précise aux éléments de logique à utiliser dans un réducteur ou un créateur d’action. Certains développeurs préfèrent avoir des créateurs d'action "en gras", avec des réducteurs "minces" qui prennent simplement les données dans une action et les fusionnent aveuglément dans l'état correspondant. D'autres essaient de mettre l'accent sur le maintien d'actions aussi petites que possible et minimisent l'utilisation de getState () dans un créateur d'actions. (Pour les besoins de cette question, d'autres approches asynchrones telles que les sagas et les observables entrent dans la catégorie "créateur d'actions".)

Ajouter plus de logique à vos réducteurs présente des avantages potentiels. Il est probable que les types d'action seraient plus sémantiques et plus significatifs (tels que "USER_UPDATED" au lieu de "SET_STATE"). De plus, le fait d'avoir plus de logique dans les réducteurs signifie que plus de fonctionnalités seront affectées par le débogage du voyage dans le temps.

Ce commentaire résume bien la dichotomie:

Maintenant, le problème est de savoir quoi mettre dans le créateur d’action et dans le réducteur, le choix entre les objets d’action épais et minces. Si vous mettez toute la logique dans le créateur d'action, vous vous retrouvez avec des objets d'action gras qui déclarent essentiellement les mises à jour de l'état. Les réducteurs deviennent purs, idiots, ajoutez-cela, supprimez-les, mettez à jour ces fonctions. Ils seront faciles à composer. Mais peu de votre logique commerciale sera là. Si vous mettez plus de logique dans le réducteur, vous vous retrouvez avec de beaux objets à action mince, la majeure partie de votre logique de données à un endroit, mais vos réducteurs sont plus difficiles à composer car vous pourriez avoir besoin d'informations provenant d'autres branches. Vous vous retrouvez avec de gros réducteurs ou des réducteurs qui prennent des arguments supplémentaires à partir des niveaux les plus élevés de l'état.

J'ai également écrit mes propres réflexions sur les réducteurs "épais et minces" :

Il y a des compromis valables à mettre plus de logique dans les créateurs d'action que de mettre plus de logique dans les réducteurs. Un point positif que j’ai vu récemment est que si vous avez plus de logique dans les réducteurs, cela signifie plus de choses pouvant être relancées si vous êtes en train de déboguer un voyage dans le temps (ce qui serait généralement une bonne chose).

Personnellement, j'ai tendance à mettre la logique aux deux endroits à la fois. J'écris aux créateurs d'action qui mettent du temps à déterminer si une action doit être envoyée et, dans l'affirmative, quel devrait en être le contenu. Cependant, j'écris aussi souvent des réducteurs correspondants qui examinent le contenu de l'action et effectuent des mises à jour d'état complexes en réponse.

11
markerikson

Certainement! Les réducteurs doivent être des fonctions pures, la logique doit donc l'être également. Cela signifie qu'il ne devrait y avoir aucun effet secondaire. Les effets secondaires incluent (sans s'y limiter):

  • Demandes de base de données/magasins
  • Fichier IO
  • Appels REST/async
  • Mutations globales ou externes
  • Des mutations de données de toutes sortes

Les réducteurs ne doivent donc jamais modifier l'état qui entre, mais renvoyer une copie avec les modifications apportées à la copie, si cela se produit. Les valeurs immuables (telles que les chaînes, les nombres, les caractères non définis, etc.) peuvent être renvoyées telles quelles, et peuvent donc indiquer si elles n'ont pas été modifiées. Si vous devez apporter des modifications aux entrées, vous renverrez une nouvelle copie ou une nouvelle valeur.

En ce qui concerne la logique appelée par votre réducteur, tant que tout ce code répond à ces exigences, vous êtes en ligne avec le modèle Redux.

Malheureusement, JavaScript ne permet pas de savoir avec certitude quand un code donné a des effets secondaires (d'autres langages le font), vous devez donc simplement savoir ce que vous appelez. 

Cela brisera-t-il Redux si vous échouez? Non, mais les choses pourraient ne pas fonctionner exactement comme vous (ou les développeurs de Flux/Redux) le souhaitez.

3
Brian Genisio

Réfléchissez à ce que vous pourriez vouloir faire dans votre middleware ... Si vous mettez toute votre logique dans votre réducteur, l'enregistrement dans le middleware n'aura pas la logique métier appliquée.

  1. dispatch (new UpdatePerson (personne))
  2. exécuter un middleware et intercepter l'action UpdatePerson
  3. réducteur - met à jour la valeur de l'âge pour la personne

si vous voulez dire, sauvegardez votre enregistrement dans un magasin, la logique de réduction s'exécutera trop tard et vous n'aurez pas accès à l'enregistrement modifié dans l'état où vous en avez besoin dans votre middleware.

0
orangesherbert