2
votes

Cet exemple de réducteur Redux du livre Pro React 16 est-il casher?

J'apprends React et Redux, et je lis actuellement Pro React 16 par Adam Freeman. Considérez ce réducteur exemple du chapitre 5. Ce réducteur gère les actions qui modifient un panier. Voici une partie du réducteur:

import { ActionTypes } from "./Types";

export const CartReducer = (storeData, action) => {
    let newStore = { cart: [], cartItems: 0, cartPrice: 0, ...storeData }
    switch(action.type) {
        case ActionTypes.CART_ADD: 
            const p = action.payload.product;
            const q = action.payload.quantity;

            let existing = newStore.cart.find(item => item.product.id === p.id);
            if (existing) {
                existing.quantity += q;
            } else {
                newStore.cart = [...newStore.cart, action.payload];
            }
            newStore.cartItems += q;
            newStore.cartPrice += p.price * q;            
            return newStore;

Je crois comprendre que les réducteurs doivent être des fonctions pures, mais celui-ci semble modifier l'argument de magasin storeData ​​code > lorsque le produit existe déjà dans le tableau cart . Plus précisément, il met à jour la propriété quantity de l'article du panier existant , qui provient d'une copie superficielle du cart code> de storeData code> tableau. Ainsi, storeData sera modifié comme effet secondaire.

Ai-je raison?


0 commentaires

3 Réponses :


0
votes

Ce n'est pas un effet secondaire. Je l'appellerais une mutation d'élément utilisé pour la création d'un nouvel état.

Ce réducteur est pur n'est pas pur mais IMHO est assez bon (quand vous connaissez le pour / contre):

  • du point de vue de l'application, il fait le travail
  • renvoie la même sortie pour la même entrée (séquence d'actions rejouable)

Le rôle du réducteur est de créer un nouvel état à partir de l'état et de l'action actuels. L'ancien état ne sera plus utilisé - cette mutation n'a pas d'importance. Il n'y a aucune obligation / restriction de laisser l'ancien état intact.

INCONVÉNIENTS: cela peut affecter les outils de développement redux, l'action d'annulation peut fonctionner de manière incorrecte (relire les actions dans une seule direction - utilisez redux-undo pour une véritable annulation)

AVANTAGES: simplicité, utilisation de la mémoire réduite

Il existe un exemple de panier dans redux < / a> - structure de données différente (plus plate).


4 commentaires

Je base mon commentaire sur la documentation redux: "Il est très important que le réducteur reste pur. Ce que vous ne devriez jamais faire à l'intérieur d'un réducteur: * Muter ses arguments ..." redux.js.org/basics/reducers


Pour une pureté stricte, vous avez raison, j'ai mis à jour la réponse.


J'apprends juste, donc vous avez peut-être raison - ça pourrait être OK en dernière analyse. Mais les documents Redux que j'ai cités sont assez clairs: "Vous ne devriez jamais ... [m] uter ses arguments."


Les réducteurs dans un usage plus général (pas seulement redux) et du point de vue de la programmation fonctionnelle devraient toujours être purs. En cas de redux, cette exception n'est qu'un petit inconvénient.



2
votes

Je pense que vous avez raison.

Non seulement vous mutez l'état (comme vous l'avez souligné), mais vous renvoyez également cet objet muté.

Je pense que vous ne devriez utiliser que la méthode 'set' d'Immutable JS pour mettre à jour l'état dans un réducteur.


0 commentaires

0
votes

Je pense que la bonne façon de créer un réducteur et de renvoyer le nouvel état est comme ci-dessous:

export default CartReducer = (storeData = [], action) => {
    switch(action.type) {
       case ActionTypes.CART_ADD: 
           return [..state, { ..action.cart }]
       default:
           return storeData;
    }
}

De cette façon, vous créez une nouvelle copie de votre état et renvoyez simplement le nouvel état , vous devez également garder votre réducteur simple et éviter de faire des choses supplémentaires comme la logique d'ajouter / mettre à jour le panier dans le code du réducteur.

Vous avez besoin également pour créer une action par défaut et renvoyer state intact .


0 commentaires