Ich habe folgenden Zustand:
this.setState({ selected: { id: 1, name: 'Foobar' } });
Dann aktualisiere ich den Status:
this.setState({ selected: { name: 'Barfoo' }});
Da setState
angenommen wird, zu verschmelzen, würde ich erwarten, dass es ist:
{ selected: { id: 1, name: 'Barfoo' } };
Aber stattdessen frisst es die ID und der Zustand ist:
{ selected: { name: 'Barfoo' } };
Ist dies das erwartete Verhalten und wie kann nur eine Eigenschaft eines verschachtelten Statusobjekts aktualisiert werden?
quelle
this.setState({ selected: { ...this.state.selected, name: 'barfoo' } })
was übersetzt wird inthis.setState({ selected: _extends({}, this.state.selected, { name: 'barfoo' }) });
underscore
/ nichtlodash
. Spinnen Sie es bitte in eine eigene Antwort.this.state
ist nicht unbedingt aktuell . Mit der Extend-Methode können Sie unerwartete Ergebnisse erzielen. Das Übergeben einer Aktualisierungsfunktion ansetState
ist die richtige Lösung.Unveränderlichkeitshilfen wurden kürzlich zu React.addons hinzugefügt. Damit können Sie jetzt Folgendes tun:
Dokumentation der Unveränderlichkeitshelfer .
quelle
React.addons.update()
Methode veraltet, aber die Ersatzbibliothek github.com/kolodny/immutability-helper enthält eine entsprechendeupdate()
Funktion.Da viele der Antworten den aktuellen Status als Grundlage für das Zusammenführen neuer Daten verwenden, wollte ich darauf hinweisen, dass dies nicht funktionieren kann. Statusänderungen werden in die Warteschlange gestellt und ändern das Statusobjekt einer Komponente nicht sofort. Wenn Sie auf Statusdaten verweisen, bevor die Warteschlange verarbeitet wurde, erhalten Sie veraltete Daten, die nicht die ausstehenden Änderungen widerspiegeln, die Sie in setState vorgenommen haben. Aus den Dokumenten:
Dies bedeutet, dass die Verwendung des "aktuellen" Status als Referenz bei nachfolgenden Aufrufen von setState unzuverlässig ist. Beispielsweise:
Wenn Sie den aktuellen Status verwenden müssen (z. B. um Daten zu einem verschachtelten Objekt zusammenzuführen), akzeptiert setState alternativ eine Funktion als Argument anstelle eines Objekts. Die Funktion wird nach vorherigen Aktualisierungen des Status aufgerufen und übergibt den Status als Argument. Auf diese Weise können atomare Änderungen vorgenommen werden, um die vorherigen Änderungen zu berücksichtigen.
quelle
this.state
dem Status , der möglicherweise veraltet ist (oder besser gesagt, die Aktualisierung in der Warteschlange ansteht), wenn Sie darauf zugreifen.Ich wollte keine weitere Bibliothek installieren, daher hier noch eine andere Lösung.
Anstatt:
Tun Sie dies stattdessen:
Oder dank @ icc97 in den Kommentaren noch prägnanter, aber wohl weniger lesbar:
Um klar zu sein, verstößt diese Antwort auch nicht gegen die oben erwähnten Bedenken von @bgannonpl.
quelle
this.setState({ selected: Object.assign(this.state.selected, { name: "Barfoo" }));
Object.assign(a, b)
nimmt Attribute vonb
, fügt sie ein / überschreibt siea
und kehrt dann zurücka
. Reagieren Sie, wenn Sie den Status direkt ändern.{}
als erstes Argument hinzufügen :this.setState({ selected: Object.assign({}, this.state.selected, { name: "Barfoo" }) });
. Dies mutiert nicht den ursprünglichen Zustand.Beibehaltung des vorherigen Status basierend auf der Antwort von @bgannonpl:
Lodash Beispiel:
Um zu überprüfen, ob es ordnungsgemäß funktioniert, können Sie den zweiten Parameterfunktionsrückruf verwenden:
Ich habe verwendet,
merge
weilextend
die anderen Eigenschaften sonst verworfen werden.Beispiel für die Unveränderlichkeit reagieren :
quelle
Meine Lösung für diese Art von Situation besteht darin, wie eine andere Antwort hervorhob , die Unveränderlichkeitshelfer zu verwenden .
Da das Einstellen des Status in der Tiefe eine häufige Situation ist, habe ich das folgende Mixin erstellt:
Dieses Mixin ist in den meisten meiner Komponenten enthalten und wird im Allgemeinen nicht
setState
mehr direkt verwendet.Mit diesem Mixin müssen Sie lediglich die Funktion
setStateinDepth
folgendermaßen aufrufen, um den gewünschten Effekt zu erzielen :Für mehr Informationen:
setStateinDepth
der Dokumentation zu Immutability Helpers .quelle
this.state.test.two
wird auch nach dem Updatethis.state.test.one
mit noch da seinsetStateInDepth({test: {one: {$set: 'new-value'}}})
. Ich verwende diesen Code in allen meinen Komponenten, um die eingeschränktesetState
Funktion von React zu umgehen .this.state.test
als Array initiiert . Wechsel zu Objekten, gelöst.Ich verwende es6-Klassen, und am Ende hatte ich mehrere komplexe Objekte in meinem obersten Status und versuchte, meine Hauptkomponente modularer zu gestalten. Deshalb habe ich einen einfachen Klassen-Wrapper erstellt, um den Status in der obersten Komponente beizubehalten, aber mehr lokale Logik zuzulassen .
Die Wrapper-Klasse übernimmt eine Funktion als Konstruktor, die eine Eigenschaft für den Hauptkomponentenstatus festlegt.
Dann erstelle ich für jede komplexe Eigenschaft im obersten Zustand eine StateWrapped-Klasse. Sie können die Standard-Requisiten hier im Konstruktor festlegen. Sie werden festgelegt, wenn die Klasse initialisiert wird. Sie können Werte auf den lokalen Status verweisen und den lokalen Status festlegen, auf lokale Funktionen verweisen und die Kette übergeben:
Dann benötigt meine Top-Level-Komponente nur den Konstruktor, um jede Klasse auf ihre Top-Level-Statuseigenschaft, ein einfaches Rendering und alle Funktionen zu setzen, die komponentenübergreifend kommunizieren.
Scheint für meine Zwecke recht gut zu funktionieren, bedenken Sie jedoch, dass Sie den Status der Eigenschaften, die Sie umschlossenen Komponenten auf der obersten Komponente zuweisen, nicht ändern können, da jede umschlossene Komponente ihren eigenen Status verfolgt, aber den Status auf der obersten Komponente aktualisiert jedes Mal, wenn es sich ändert.
quelle
Ab sofort
gemäß der Dokumentation https://reactjs.org/docs/react-component.html#setstate unter Verwendung von:
quelle
Lösung
Bearbeiten: Diese Lösung verwendet die Spread-Syntax . Das Ziel war es, ein Objekt ohne Verweise darauf zu erstellen
prevState
, damitprevState
es nicht geändert wird. Aber in meiner VerwendungprevState
schien manchmal geändert. Für ein perfektes Klonen ohne Nebenwirkungen konvertieren wir jetztprevState
zu JSON und dann wieder zurück. (Die Inspiration zur Verwendung von JSON kam von MDN .)Merken:
setState(prevState => stateChange)
Schritte
state
die Sie ändern wollenDie Schritte 3 und 4 können in einer Zeile kombiniert werden.
Beispiel
Vereinfachtes Beispiel:
Dies folgt gut den React-Richtlinien. Basierend auf der Antwort von eicksl auf eine ähnliche Frage.
quelle
ES6-Lösung
Wir setzen den Zustand zunächst
Wir ändern eine Eigenschaft auf einer bestimmten Ebene des Statusobjekts:
quelle
Der Reaktionsstatus führt die rekursive Zusammenführung nicht durch,
setState
erwartet jedoch, dass nicht gleichzeitig Aktualisierungen der Statusstatusmitglieder durchgeführt werden. Sie müssen entweder eingeschlossene Objekte / Arrays selbst kopieren (mit array.slice oder Object.assign) oder die dedizierte Bibliothek verwenden.Wie dieser. NestedLink unterstützt direkt die Behandlung des zusammengesetzten Reaktionszustands.
Außerdem kann der Link zum
selected
oderselected.name
überall als einzelne Requisite weitergegeben und dort mit modifiziert werdenset
.quelle
Hast du den Ausgangszustand eingestellt?
Ich werde zum Beispiel einen Teil meines eigenen Codes verwenden:
In einer App, an der ich arbeite, habe ich den Status so eingestellt und verwendet. Ich glaube,
setState
Sie können dann einfach die gewünschten Zustände individuell bearbeiten. Ich habe es so genannt:Denken Sie daran,
React.createClass
dass Sie den Status innerhalb der von Ihnen aufgerufenen Funktion festlegen müssengetInitialState
quelle
Ich benutze die tmp var um zu ändern.
quelle
let original = {a:1}; let tmp = original; tmp.a = 5; // original is now === Object {a: 5}
Tun Sie dies nicht, auch wenn es Ihnen noch keine Probleme bereitet hat.