TL; DR
Ohne combineReducers()
oder ähnlichen manuellen Code initialState
gewinnt immer state = ...
im Reduzierer, weil der state
an 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 initialState
ist, erhalten dies state
. Andere Reduzierer erhalten undefined
und greifen daher auf das von state = ...
ihnen angegebene Standardargument zurück.
Im Allgemeinen initialState
gewinnt 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 createStore
war undefined
. Dies wird state
beim 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 counter
Reduzierer mit state
gleich aufgerufen undefined
. Dies ist genau der Fall, der das Standardargument „aktiviert“. Daher entspricht state
jetzt 0
der 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 42
nicht und nicht 0
? Da createStore
wurde mit 42
als zweites Argument aufgerufen . Dieses Argument wird state
zusammen mit der Dummy-Aktion an Ihren Reduzierer übergeben. Dieses Mal state
ist nicht undefiniert (es ist 42
!), Daher hat die ES6-Standardargumentsyntax keine Auswirkung. Das state
ist 42
und 42
wird 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 , createStore
ohne das initialState
, es wird die initialisieren state
zu {}
. Daher state.a
und state.b
wird es zu undefined
dem Zeitpunkt sein, an dem es anruft a
und b
reduziert. Sowohl a
und b
Reduzierungen erhalten undefined
als 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 initialState
als Argument angegeben createStore()
. Der vom kombinierten Reduzierer zurückgegebene Status kombiniert den für den a
Reduzierer angegebenen Anfangszustand mit dem 'wat'
Standardargument, das der b
Reduzierer 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 state
wurde angegeben, dass nicht darauf zurückgegriffen wurde {}
. Es war ein Objekt mit einem a
Feld gleich 'horse'
, aber ohne b
Feld. Dies ist der Grund, warum der a
Reduzierer 'horse'
als sein empfangen state
und es gerne zurückgegeben hat, aber der b
Reduzierer undefined
als sein empfangen hat state
und 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 undefined
als state
Argument aufgerufen werden (der einfachste Weg, dies zu implementieren, besteht darin, den state
ES6-Standardargumentwert anzugeben ) ein schönes nützliches Verhalten für kombinierte Reduzierstücke. Sie bevorzugen den entsprechenden Wert in dem initialState
Objekt, 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.function counter(state = 0, action)
oderfunction visibleIds(state = [], action)
.Kurz gesagt: Es ist Redux, der den Ausgangszustand an die Reduzierer weitergibt. Sie müssen nichts tun.
Wenn Sie anrufen
createStore(reducer, [initialState])
, teilen Sie Redux mit, welcher Ausgangszustand an den Reduzierer übergeben werden soll, wenn die erste Aktion eingeht.Die zweite Option, die Sie erwähnen, gilt nur für den Fall, dass Sie beim Erstellen des Geschäfts keinen Anfangszustand überschritten haben. dh
function todoApp(state = initialState, action)
Der Status wird nur initialisiert, wenn kein Status von Redux übergeben wurde
quelle
menuState
, wie kann ich den Menü-Reduzierer anweisen, den Wert vonstate.menu
aus dem Geschäft zu lesen und diesen als Ausgangszustand zu verwenden?kombinReduzierer () erledigen den Job für Sie. Der erste Weg, es zu schreiben, ist nicht wirklich hilfreich:
Aber der andere, der gleichwertig ist, ist klarer:
quelle
Ich hoffe, dies beantwortet Ihre Anfrage (die ich als Initialisieren von Reduzierungen beim Übergeben von intialState und Zurückgeben dieses Status verstanden habe).
So machen wir das (Warnung: aus Typescript-Code kopiert).
Das Wesentliche ist der
if(!state)
Test in der Funktion mainReducer (Factory)quelle