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?
La différence est:
combineReducers
crée l'état nestedreduceReducers
crée l'état flatConsidé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
}
}
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
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
* }
*/
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.
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.
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