Ich habe unzählige Dokumentationen gelesen - auf allen beliebten Websites - aber nirgends habe ich eine Antwort gefunden. Ich frage hier, ob ich eine Dokumentation oder ein wichtiges Verständnis verpasst habe.
Das Problem, das ich sehe, ist, dass die mapStateToProps () -Funktion meiner Komponente nur einmal (bei der Initialisierung) aufgerufen wird. Es wird nie wieder aufgerufen, auch wenn der Reduzierer aufgerufen wird. Ich fange an zu denken, dass es daran liegt, dass ich nicht verstehe, wie Aktionen / Reduzierer / Requisiten miteinander verbunden sind.
Lassen Sie mich zuerst sagen, was ich weiß:
Aber ... Ich habe keine Beschreibung gefunden, wie Aktionen, Reduzierungen und mapStateToProps miteinander zusammenhängen. Meine Fragen:
Haben Sie http://redux.js.org/docs/Troubleshooting.html durchgesehen und überprüft, ob Ihr Fall nicht zu den darin beschriebenen Problemen gehört?
Ich stelle mir den Speicher als Objekt vor, mit Eigenschaften, die Daten über den Status der Anwendung enthalten. Diese Eigenschaften der obersten Ebene können Objekte sein, die einen Unterbaum zum Speichern von Informationen zu einem Teil der Anwendung bereitstellen. Ist das wahr?
Ja. Store enthält das Statusobjekt der obersten Ebene intern. Es bietet Zugriff auf dieses Objekt von store.getState()
. Dieses Objekt entspricht dem, was Sie vom Root-Reduzierer zurückgeben, und es ist oft baumartig.
Welche Eigenschaft (oder Unterbaum des Geschäfts) wird aktualisiert, wenn eine Aktion an das Geschäft gesendet wird? Es scheint, dass eine Eigenschaft innerhalb des Geschäfts automatisch erstellt / zugeordnet wird, aber wie wird dies bestimmt?
Nein, es wird nichts automatisch erstellt. Der Store zeigt gerade auf das Ergebnis des Aufrufs Ihres Root-Reduzierers.
Wenn Ihr Root-Reducer eine Funktion ist, die Sie selbst geschrieben haben, erhalten Sie das Ergebnis, nachdem Sie eine Aktion ausgelöst haben:
function counter(state = 0, action) {
if (action.type === 'INCREMENT') {
return state + 1; // will become the next value of store.getState() after store.dispatch()
}
return state;
}
Wenn Sie den Root-Reducer mit so etwas wie combineReducers({ foo, bar })
generieren, ist es dasselbe, als hätten Sie einen Root-Reducer von Hand geschrieben, der so aussieht:
function root(state = {}, action) {
return {
foo: foo(state.foo, action),
bar: bar(state.bar, action)
}
}
Hierher kommen oft die Eigenschaften des Staates. Ihre Werte werden durch die Rückgabe Ihrer foo
und bar
-Reduzierer während der Ausführung der Aktion bestimmt, sodass Sie wieder die volle Kontrolle über sie haben.
Woher "weiß" mapStateToProps, dass es auf Aktualisierungen der richtigen Eigenschaft / des richtigen Teils des Geschäfts wartet? Was verbindet sie?
Sie übergeben die Funktion mapStateToProps
an connect()
. Es wird eine Komponente generiert, die store.subscribe()
, um jede Änderung am Geschäft abzuhören. Wenn sich das Geschäft geändert hat, liest die generierte Komponente store.getState()
und übergibt sie an mapStateToProps()
, um die nächsten weitergegebenen Requisiten zu bestimmen. Wenn sie sich geändert haben, wird Ihre Komponente mit ihnen neu gerendert.
Wie könnte ich das debuggen? Was muss ich tun, um herauszufinden, warum das Versenden der Aktion mapStateToProps nicht auslöst?
Fügen Sie eine Middleware wie https://github.com/theaqua/redux-logger hinzu. Stellen Sie sicher, dass der Status nach der Aktion wie erwartet aktualisiert wird. Wenn mapStateToProps
nicht einmal angerufen wird, bedeutet das, dass
dispatch()
eine Aktion auszuführen und haben gerade einen Aktionsersteller angerufen.connect()
sich nicht die Mühe gemacht hat, mapStateToProps()
.Beide Fälle sind unter http://redux.js.org/docs/Troubleshoot.html beschrieben.
In Zukunft bitten wir Sie, zuerst Fragen zu StackOverflow zu stellen und den Issue-Tracker zu verwenden, wenn Sie sicher sind, dass die Bibliothek einen Fehler enthält, den Sie anhand eines Beispiels, das Sie freigeben können, konsistent reproduzieren können.
Vielen Dank!
Antwort in der richtigen Reihenfolge:
{ users : {}, posts : {}, comments : {}, ui : {} }
. Siehe http://redux.js.org/docs/FAQ.html#reducers -share-state und http://redux.js.org/docs/FAQ.html#organizing -state-nested-data.combineReducers
macht es einfach, eine bestimmte Reduzierungsfunktion zu haben, die für die Verwaltung von Aktualisierungen eines bestimmten Datenabschnitts verantwortlich ist, z. B.: const combinedReducer = combineReducers({users : userReducer, posts : postReducer, comments : commentsReducer, ui : uiReducer});
connect()
-Funktion abonniert und ruft dann die mapStateToProps
der Komponente http://redux.js.org/docs/FAQ.html#store -setup-subscriptions.Hoffentlich hilft das, die Dinge zu klären.
Darüber hinaus, wie Dan sagte: Nutzungsfragen sind im Allgemeinen besser für den Stapelüberlauf geeignet. Außerdem verfügt die Reactiflux-Community auf Discord über eine Reihe von Chat-Kanälen, die sich mit reaktionsbezogenen Technologien befassen, einschließlich Redux, und es gibt immer eine Reihe von Leuten, die bereit sind, Fragen zu beantworten. Es gibt einen Einladungslink unter https://www.reactiflux.com .
@ richb-hanover Sie haben wahrscheinlich den flachen Vergleich gesehen, der von der React-Redux-Verbindung durchgeführt wird. Dies bedeutet, dass in anderen Objekten verschachtelte Objekte auch dann nicht erneut gerendert werden, wenn sie geändert werden, da nur der Stammschlüssel auf Änderungen überprüft wird.
http://redux.js.org/docs/faq/ReactRedux.html#why -isnt-my-component-re-rendering-or-my-mapstatetoprops-running
@ richb-hanover In meinem Fall hat @gaearon das Problem festgestellt:
Oder Ihr Reduzierer hat einen referenziell identischen Wert zurückgegeben, sodass connect () sich nicht die Mühe gemacht hat, mapStateToProps () aufzurufen.
Ich habe dieses Update verwendet und dies war der resultierende Code
const mapStateToProps = (state, props) => {
return { id: props.id, currentState: state[props.id] };
}
const mapDispatchToProps = (dispatch) => {
return {
increment: (id) => {
dispatch({ type: 'INCREMENT', id: id })
}
}
}
const DumbListItem = ({
increment,
id,
currentState
}) => (
<div>
<li onClick={() => increment()}>{id}</li>
<span>{currentState}</span>
</div>
);
export const ConnectedListItem = connect(
mapStateToProps,
mapDispatchToProps
)(DumbListItem);
Da ich den Parameter id
an den Inkrementaufruf übergeben habe (entweder als increment(id)
in der Vorlage oder über den zweiten Parameter in mapDispatchToProps
), hat der Store dies nicht getan Aktualisieren Sie das Update. Überprüfen Sie daher, ob dies möglicherweise Ihr Problem ist.
Hilfreichster Kommentar
Haben Sie http://redux.js.org/docs/Troubleshooting.html durchgesehen und überprüft, ob Ihr Fall nicht zu den darin beschriebenen Problemen gehört?
Ja. Store enthält das Statusobjekt der obersten Ebene intern. Es bietet Zugriff auf dieses Objekt von
store.getState()
. Dieses Objekt entspricht dem, was Sie vom Root-Reduzierer zurückgeben, und es ist oft baumartig.Nein, es wird nichts automatisch erstellt. Der Store zeigt gerade auf das Ergebnis des Aufrufs Ihres Root-Reduzierers.
Wenn Ihr Root-Reducer eine Funktion ist, die Sie selbst geschrieben haben, erhalten Sie das Ergebnis, nachdem Sie eine Aktion ausgelöst haben:
Wenn Sie den Root-Reducer mit so etwas wie
combineReducers({ foo, bar })
generieren, ist es dasselbe, als hätten Sie einen Root-Reducer von Hand geschrieben, der so aussieht:Hierher kommen oft die Eigenschaften des Staates. Ihre Werte werden durch die Rückgabe Ihrer
foo
undbar
-Reduzierer während der Ausführung der Aktion bestimmt, sodass Sie wieder die volle Kontrolle über sie haben.Sie übergeben die Funktion
mapStateToProps
anconnect()
. Es wird eine Komponente generiert, diestore.subscribe()
, um jede Änderung am Geschäft abzuhören. Wenn sich das Geschäft geändert hat, liest die generierte Komponentestore.getState()
und übergibt sie anmapStateToProps()
, um die nächsten weitergegebenen Requisiten zu bestimmen. Wenn sie sich geändert haben, wird Ihre Komponente mit ihnen neu gerendert.Fügen Sie eine Middleware wie https://github.com/theaqua/redux-logger hinzu. Stellen Sie sicher, dass der Status nach der Aktion wie erwartet aktualisiert wird. Wenn
mapStateToProps
nicht einmal angerufen wird, bedeutet das, dassdispatch()
eine Aktion auszuführen und haben gerade einen Aktionsersteller angerufen.connect()
sich nicht die Mühe gemacht hat,mapStateToProps()
.Beide Fälle sind unter http://redux.js.org/docs/Troubleshoot.html beschrieben.
In Zukunft bitten wir Sie, zuerst Fragen zu StackOverflow zu stellen und den Issue-Tracker zu verwenden, wenn Sie sicher sind, dass die Bibliothek einen Fehler enthält, den Sie anhand eines Beispiels, das Sie freigeben können, konsistent reproduzieren können.
Vielen Dank!