web-dev-qa-db-fra.com

utilisation correcte des réducteurs réducteurs

Je ne comprends pas à quoi sert réduire-réducteurs . Doit-il être utilisé dans le cas où j'ai 2 fonctions de réduction contenant la même action? 

function reducerA(state, action){
   switch(action.type):
       ...
       case 'SAME_ACTION': {...state, field: state.field+1}
}

function reducerB(state, action){
   switch(action.type):
       ...
       case 'SAME_ACTION': {...state, field: state.field*2}
}

Donc, si j'appelle reduceReducer sur reducerA et reducerB et que l'action 'SAME_ACTION' est appelée pour {field: 0}, j'aurais alors le prochain état {field: 2}?

De plus, il me semble que cela concatène en quelque sorte les réducteurs (ce qui signifie les fusionner sous une clé). 

Ai-je raison ou est-ce que reduceReducer a un but différent?

22
Amio.io

La différence est:

  • combineReducers crée l'état nested
  • reduceReducers crée l'état flat

Considérez les réducteurs suivants. Il n'y a pas de types d'action pour simplifier les choses:

// this reducer adds a payload to state.sum 
// and tracks total number of operations
function reducerAdd(state, payload) {
  if (!state) state = { sum: 0, totalOperations: 0 }
  if (!payload) return state

  return {
    ...state,
    sum: state.sum + payload,
    totalOperations: state.totalOperations + 1
  }
}

// this reducer multiplies state.product by payload
// and tracks total number of operations
function reducerMult(state, payload) {
  if (!state) state = { product: 1, totalOperations: 0 }
  if (!payload) return state

  // `product` might be undefined because of 
  // small caveat in `reduceReducers`, see below
  const prev = state.product || 1

  return {
    ...state,
    product: prev * payload,
    totalOperations: state.totalOperations + 1
  }
}

combiner des réducteurs

Chaque réducteur obtient un état indépendant (voir aussi http://redux.js.org/docs/api/combineReducers.html ):

const rootReducer = combineReducers({
  add: reducerAdd,
  mult: reducerMult
})

const initialState = rootReducer(undefined)
/*
 * {
 *   add:  { sum: 0, totalOperations: 0 },
 *   mult: { product: 1, totalOperations: 0 },
 * }
 */


const first = rootReducer(initialState, 4)
/*
 * {
 *   add:  { sum: 4, totalOperations: 1 },
 *   mult: { product: 4, totalOperations: 1 },
 * }
 */    
// This isn't interesting, let's look at second call...

const second = rootReducer(first, 4)
/*
 * {
 *   add:  { sum: 8, totalOperations: 2 },
 *   mult: { product: 16, totalOperations: 2 },
 * }
 */
// Now it's obvious, that both reducers get their own 
// piece of state to work with

réduire les réducteurs

Tous les réducteurs partagent le même état 

const addAndMult = reducerReduce(reducerAdd, reducerMult) 

const initial = addAndMult(undefined)
/* 
 * {
 *   sum: 0,
 *   totalOperations: 0
 * }
 *
 * First, reducerAdd is called, which gives us initial state { sum: 0 }
 * Second, reducerMult is called, which doesn't have payload, so it 
 * just returns state unchanged. 
 * That's why there isn't any `product` prop.
 */ 

const next = addAndMult(initial, 4)
/* 
 * {
 *   sum: 4,
 *   product: 4,
 *   totalOperations: 2
 * }
 *
 * First, reducerAdd is called, which changes `sum` = 0 + 4 = 4
 * Second, reducerMult is called, which changes `product` = 1 * 4 = 4
 * Both reducers modify `totalOperations`
 */


const final = addAndMult(next, 4)
/* 
 * {
 *   sum: 8,
 *   product: 16,
 *   totalOperations: 4
 * }
 */

Cas d'utilisation

  • combineReducers - chaque réducteur gère sa propre tranche d’état (par exemple, state.todos et state.logging). Ceci est utile lors de la création d'un réducteur racine.
  • reduceReducers - chaque réducteur gère le même état. Ceci est utile pour chaîner plusieurs réducteurs supposés fonctionner sur le même état (ceci peut arriver par exemple lors de la combinaison de plusieurs réducteurs créés avec handleAction à partir de redux-actions )

La différence est évidente à partir de la forme de l'état final.

Mises en garde

Il y a une petite mise en garde dans reduceReducers: Lorsque le réducteur final est appelé avec state = undefined, il devrait renvoyer l'état initial. Cependant, seul le premier réducteur de la chaîne reçoit undefined, tous les autres réducteurs recevront l'état du premier.

53
Tomáš Ehrlich

Je ne comprends pas non plus ce que les réducteurs réducteurs essaient de résoudre. Le cas d'utilisation décrit par @ Tomáš peut être réalisé à l'aide d'un simple réducteur. Après tout, Reducer est simplement une fonction qui accepte l’état de l’application et une action, et renvoie un objet contenant le nouvel état de l’application. Par exemple, vous pouvez effectuer les opérations suivantes au lieu d'utiliser les combine combineReducers fournies par redux:

import combinationReducer from "./combinationReducer";
import endOfPlayReducer from "./endOfPlayReducer";
import feedbackReducer from "./feedbackReducer";

function combineReducers(appState, action) {
  return {
    combination: combinationReducer(appState, action),
    feedbacks: feedbackReducer(appState, action),
    endOfPlay: endOfPlayReducer(appState, action)
  };
}

Et bien sûr, ici, vos réducteurs acceptent l’ensemble de l’état de l’application et ne renvoient que la tranche dont ils sont responsables. Encore une fois, c'est juste une fonction, vous pouvez la personnaliser comme bon vous semble. Vous pouvez en lire plus à ce sujet ici

0
Behnam Rasooli