TL; DR
Ohne combineReducers()oder ähnlichen manuellen Code initialStategewinnt immer state = ...im Reduzierer, weil der statean den Reduzierer übergebene ist initialState und nicht undefined , so dass die ES6-Argumentsyntax in diesem Fall nicht angewendet wird.
Mit combineReducers()dem Verhalten wird nuancierter. Diejenigen Reduzierer, deren Zustand in angegeben initialStateist, erhalten dies state. Andere Reduzierer erhalten undefined und greifen daher auf das von state = ...ihnen angegebene Standardargument zurück.
Im Allgemeinen initialStategewinnt der vom Reduzierer angegebene Zustand. Auf diese Weise können Reduzierer Anfangsdaten angeben, die für sie als Standardargumente sinnvoll sind , aber auch vorhandene Daten (ganz oder teilweise) laden, wenn Sie den Speicher von einem dauerhaften Speicher oder vom Server aus hydratisieren.
Betrachten wir zunächst einen Fall, in dem Sie einen einzelnen Reduzierer haben.
Angenommen, Sie verwenden nicht combineReducers().
Dann könnte Ihr Reduzierer so aussehen:
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT': return state - 1;
default: return state;
}
}
Angenommen, Sie erstellen damit ein Geschäft.
import { createStore } from 'redux';
let store = createStore(counter);
console.log(store.getState()); // 0
Der Ausgangszustand ist Null. Warum? Weil das zweite Argument createStorewar undefined. Dies wird statebeim ersten Mal an Ihren Reduzierer übergeben. Wenn Redux initialisiert wird, wird eine "Dummy" -Aktion ausgelöst, um den Status zu füllen. Also wurde Ihr counterReduzierer mit stategleich aufgerufen undefined. Dies ist genau der Fall, der das Standardargument „aktiviert“. Daher entspricht statejetzt 0der Standardwert state( state = 0). Dieser Zustand ( 0) wird zurückgegeben.
Betrachten wir ein anderes Szenario:
import { createStore } from 'redux';
let store = createStore(counter, 42);
console.log(store.getState()); // 42
Warum ist es diesmal 42nicht und nicht 0? Da createStorewurde mit 42als zweites Argument aufgerufen . Dieses Argument wird statezusammen mit der Dummy-Aktion an Ihren Reduzierer übergeben. Dieses Mal stateist nicht undefiniert (es ist 42!), Daher hat die ES6-Standardargumentsyntax keine Auswirkung. Das stateist 42und 42wird vom Reduzierstück zurückgegeben.
Betrachten wir nun einen Fall, in dem Sie verwenden combineReducers().
Sie haben zwei Reduzierungen:
function a(state = 'lol', action) {
return state;
}
function b(state = 'wat', action) {
return state;
}
Der von erzeugte Reduzierer combineReducers({ a, b })sieht folgendermaßen aus:
// const combined = combineReducers({ a, b })
function combined(state = {}, action) {
return {
a: a(state.a, action),
b: b(state.b, action)
};
}
Wenn wir anrufen , createStoreohne das initialState, es wird die initialisieren statezu {}. Daher state.aund state.bwird es zu undefineddem Zeitpunkt sein, an dem es anruft aund breduziert. Sowohl aund bReduzierungen erhalten undefinedals ihre state Argumente, und wenn sie angeben , Standardwerte,state werden diese zurückgeführt werden. Auf diese Weise gibt der kombinierte Reduzierer { a: 'lol', b: 'wat' }beim ersten Aufruf ein Statusobjekt zurück .
import { createStore } from 'redux';
let store = createStore(combined);
console.log(store.getState()); // { a: 'lol', b: 'wat' }
Betrachten wir ein anderes Szenario:
import { createStore } from 'redux';
let store = createStore(combined, { a: 'horse' });
console.log(store.getState()); // { a: 'horse', b: 'wat' }
Jetzt habe ich das initialStateals Argument angegeben createStore(). Der vom kombinierten Reduzierer zurückgegebene Status kombiniert den für den aReduzierer angegebenen Anfangszustand mit dem 'wat'Standardargument, das der bReduzierer selbst ausgewählt hat.
Erinnern wir uns, was der kombinierte Reduzierer tut:
// const combined = combineReducers({ a, b })
function combined(state = {}, action) {
return {
a: a(state.a, action),
b: b(state.b, action)
};
}
In diesem Fall statewurde angegeben, dass nicht darauf zurückgegriffen wurde {}. Es war ein Objekt mit einem aFeld gleich 'horse', aber ohne bFeld. Dies ist der Grund, warum der aReduzierer 'horse'als sein empfangen stateund es gerne zurückgegeben hat, aber der bReduzierer undefinedals sein empfangen hat stateund somit seine Idee des Standards zurückgegeben hat state(in unserem Beispiel 'wat'). So kommen wir { a: 'horse', b: 'wat' }zurück.
Um dies zusammenzufassen: Wenn Sie sich an Redux-Konventionen halten und den Anfangszustand von Reduzierern zurückgeben, wenn diese undefinedals stateArgument aufgerufen werden (der einfachste Weg, dies zu implementieren, besteht darin, den stateES6-Standardargumentwert anzugeben ) ein schönes nützliches Verhalten für kombinierte Reduzierstücke. Sie bevorzugen den entsprechenden Wert in dem initialStateObjekt, das Sie an die createStore()Funktion übergeben. Wenn Sie jedoch keinen übergeben haben oder wenn das entsprechende Feld nicht festgelegt ist, wird der Standardwert verwendet.state ist, wird stattdessen das vom Reduzierer angegebene ausgewählt.Dieser Ansatz funktioniert gut, da er sowohl die Initialisierung als auch die Hydratisierung vorhandener Daten ermöglicht, es jedoch einzelnen Reduzierern ermöglicht, ihren Status zurückzusetzen, wenn ihre Daten nicht erhalten wurden. Natürlich können Sie dieses Muster rekursiv anwenden, da Sie es combineReducers()auf vielen Ebenen verwenden können, oder sogar Reduzierungen manuell erstellen, indem Sie Reduzierungen aufrufen und ihnen den relevanten Teil des Statusbaums zuweisen.
combineReducers. Nochmals vielen Dank.