Ich versuche, meinen Status mithilfe einer verschachtelten Eigenschaft wie folgt zu organisieren:
this.state = {
someProperty: {
flag:true
}
}
Aber den Status so aktualisieren,
this.setState({ someProperty.flag: false });
funktioniert nicht Wie kann das richtig gemacht werden?
javascript
reactjs
ecmascript-6
setstate
Alex Yong
quelle
quelle
Antworten:
Um
setState
ein verschachteltes Objekt zu erhalten, können Sie den folgenden Ansatz verfolgen, da setState meiner Meinung nach keine verschachtelten Aktualisierungen verarbeitet.Die Idee ist, ein Dummy-Objekt zu erstellen, Operationen daran auszuführen und dann den Status der Komponente durch das aktualisierte Objekt zu ersetzen
Jetzt erstellt der Spread-Operator nur eine verschachtelte Kopie des Objekts auf einer Ebene. Wenn Ihr Bundesstaat stark verschachtelt ist wie:
Sie können setState mit dem Spread-Operator auf jeder Ebene wie setzen
Die obige Syntax wird jedoch immer hässlicher, wenn der Status immer verschachtelter wird. Daher empfehle ich Ihnen, das
immutability-helper
Paket zum Aktualisieren des Status zu verwenden.In dieser Antwort erfahren Sie, wie Sie den Status aktualisieren
immutability helper
.quelle
someProperty
und wir diesthis.setState((prevState) => ({nested: {...prevState.nested, propertyToSet: newValue}})
Ein bisschen langweilig ......prevState,
im letzten Beispiel brauchen , Sie nursomeProperty
und seine KinderUm es in einer Zeile zu schreiben
quelle
this.state
gleich danachsetState
und erwarten Sie, dass es den neuen Wert hat. Versus Aufrufthis.state
innerhalbsetState
. Oder gibt es auch ein Problem mit letzterem, das mir nicht klar ist?this.state
nachsetState
. Außerdem passieren wir nichtthis.state
zusetState
. Der…
Operator verteilt Eigenschaften. Es ist dasselbe wie Object.assign (). github.com/tc39/proposal-object-rest-spreadthis.setState(currentState => { someProperty: { ...currentState.someProperty, flag: false} });
könnte erlauben, dieses Problem zu vermeiden?Manchmal sind direkte Antworten nicht die besten :)
Kurzfassung:
dieser Code
sollte als so etwas vereinfacht werden
Lange Version:
Derzeit sollten Sie nicht mit dem verschachtelten Status in React arbeiten möchten . Da React nicht darauf ausgerichtet ist, mit verschachtelten Zuständen zu arbeiten, sehen alle hier vorgeschlagenen Lösungen als Hacks aus. Sie nutzen das Framework nicht, sondern kämpfen damit. Sie schlagen vor, nicht so klaren Code zu schreiben, um einige Eigenschaften zweifelhaft zu gruppieren. Sie sind als Antwort auf die Herausforderung sehr interessant, aber praktisch nutzlos.
Stellen wir uns folgenden Zustand vor:
Was passiert, wenn Sie nur einen Wert von ändern
child1
? React rendert die Ansicht nicht erneut, da ein flacher Vergleich verwendet wird und festgestellt wird, dass sich dieparent
Eigenschaft nicht geändert hat. Übrigens wird das direkte Mutieren des Zustandsobjekts im Allgemeinen als schlechte Praxis angesehen.Sie müssen also das gesamte
parent
Objekt neu erstellen . In diesem Fall werden wir jedoch auf ein anderes Problem stoßen. React wird denken, dass alle Kinder ihre Werte geändert haben und sie alle neu rendern. Natürlich ist es nicht gut für die Leistung.Es ist immer noch möglich, dieses Problem durch Schreiben einer komplizierten Logik zu lösen,
shouldComponentUpdate()
aber ich würde es vorziehen, hier anzuhalten und eine einfache Lösung aus der Kurzversion zu verwenden.quelle
Haftungsausschluss
die Antwort auf Ihr Elend - siehe Beispiel hier
Es gibt eine andere kürzere Möglichkeit, verschachtelte Eigenschaften zu aktualisieren.
In einer Zeile
Hinweis: Dies hier ist der Komma-Operator ~ MDN . Sehen Sie ihn hier in Aktion (Sandbox) .
Es ist ähnlich (obwohl dies die Zustandsreferenz nicht ändert)
Für den subtilen Unterschied in diesem Zusammenhang zwischen
forceUpdate
undsetState
siehe das verknüpfte Beispiel.Natürlich missbraucht dies einige Kernprinzipien, da
state
diese schreibgeschützt sein sollten, aber da Sie den alten Zustand sofort verwerfen und durch einen neuen Zustand ersetzen, ist dies völlig in Ordnung.Warnung
Auch wenn die Komponente den Zustand enthält , wird aktualisiert und rerender richtig ( mit Ausnahme dieser Gotcha ) , werden die Requisiten nicht auf Kinder zu verbreiten (siehe Spymaster Kommentar unten) . Verwenden Sie diese Technik nur, wenn Sie wissen, was Sie tun.
Beispielsweise können Sie eine geänderte flache Requisite übergeben, die aktualisiert und problemlos übergeben werden kann.
Jetzt, obwohl sich die Referenz für complexNestedProp nicht geändert hat ( shouldComponentUpdate )
Die Komponente wird bei jeder Aktualisierung der übergeordneten Komponente erneut gerendert, was nach dem Aufruf
this.setState
oderthis.forceUpdate
im übergeordneten Element der Fall ist .Auswirkungen der Mutation des Staates
Die Verwendung eines verschachtelten Status und die direkte Mutation des Status ist gefährlich, da verschiedene Objekte möglicherweise (absichtlich oder nicht) unterschiedliche (ältere) Verweise auf den Status enthalten und nicht unbedingt wissen, wann sie aktualisiert werden müssen (z. B. wenn sie verwendet werden
PureComponent
oder wennshouldComponentUpdate
sie für die Rückgabe implementiert sindfalse
) ODER sind soll alte Daten wie im folgenden Beispiel anzeigen.Wie auch immer, hier können Sie sehen, dass
Nested PureChildClass
es nicht neu gerendert wurde, weil Requisiten sich nicht verbreiten konnten.quelle
state
vollständig Gräben bildet und benutzerdefinierte beobachtbare Eigenschaften verwendet. React'ssetState
ist nur eine eingebaute Annehmlichkeit, aber Sie werden schnell feststellen, dass es seine Grenzen hat. Durch die Verwendung benutzerdefinierter Eigenschaften und die intelligente Verwendung von erhaltenforceUpdate
Sie viel mehr. Verwenden Sie in React-Komponenten Observables anstelle von state.this.forceUpdate()
bestimmte Objekte auszulösen oder zu implementierenshouldComponentUpdate
.Wenn Sie ES2015 verwenden, haben Sie Zugriff auf die Object.assign. Sie können es wie folgt verwenden, um ein verschachteltes Objekt zu aktualisieren.
Sie führen die aktualisierten Eigenschaften mit den vorhandenen zusammen und verwenden das zurückgegebene Objekt, um den Status zu aktualisieren.
Bearbeiten: Der Zuweisungsfunktion wurde ein leeres Objekt als Ziel hinzugefügt, um sicherzustellen, dass der Status nicht direkt mutiert wird, wie Carkod hervorhob.
quelle
quelle
property
mehrere verschachtelte Eigenschaften enthält, löscht die erste diese, die zweite nicht. Codesandbox.io/s/nameless-pine-42thuEs gibt viele Bibliotheken, die dabei helfen. Zum Beispiel mit Unveränderlichkeitshelfer :
Mit lodash / fp set:
Verwenden von lodash / fp merge:
quelle
lodash
, möchten Sie wahrscheinlich versuchen_.cloneDeep
, den Status als geklonte Kopie festzulegen.lodash/fp
, damit wir uns keine Gedanken über Mutationen machen müssen.merge
oderset
Funktionen in lodash / fp neben der Syntax?this.setState(newState)
die lodash / fp-Methoden aufrufen müssen. Ein weiteres Problem ist, dass lodash.set
(non-fp) eine andere Reihenfolge von Argumenten hat, die mich für eine Weile gestolpert haben.Wir verwenden Immer https://github.com/mweststrate/immer , um diese Art von Problemen zu behandeln.
Ersetzen Sie einfach diesen Code in einer unserer Komponenten
Mit diesem
Mit immer behandeln Sie Ihren Zustand als "normales Objekt". Die Magie geschieht hinter den Kulissen mit Proxy-Objekten.
quelle
Hier ist eine Variation der ersten Antwort in diesem Thread, für die keine zusätzlichen Pakete, Bibliotheken oder Sonderfunktionen erforderlich sind.
Um den Status eines bestimmten verschachtelten Felds festzulegen, haben Sie das gesamte Objekt festgelegt. Dazu habe ich eine Variable erstellt
newState
und den Inhalt des aktuellen Status zuerst mit dem Spreizoperator ES2015 in ihn verteilt . Dann habe ich den Wert vonthis.state.flag
durch den neuen Wert ersetzt (da ich festgelegt habe,flag: value
nachdem ich den aktuellen Status in das Objekt verteilt habe, wird dasflag
Feld im aktuellen Status überschrieben). Dann setze ich einfach den StatussomeProperty
auf meinnewState
Objekt.quelle
Obwohl das Verschachteln nicht wirklich so ist, wie Sie einen Komponentenzustand behandeln sollten, ist es manchmal einfach, das Verschachteln in einer Ebene zu vereinfachen.
Für einen Staat wie diesen
Eine wiederverwendbare Methode würde so aussehen.
Geben Sie dann einfach den obj-Namen für jede Verschachtelung ein, die Sie adressieren möchten ...
quelle
Ich habe diese Lösung verwendet.
Wenn Sie einen verschachtelten Status wie diesen haben:
Sie können die handleChange-Funktion deklarieren, die den aktuellen Status kopiert und ihn mit geänderten Werten neu zuweist
hier das html mit dem event listener
quelle
Erstellen Sie eine Kopie des Status:
Nehmen Sie Änderungen an diesem Objekt vor:
Aktualisieren Sie jetzt den Status
quelle
Obwohl Sie nach dem Status einer klassenbasierten React-Komponente gefragt haben, besteht das gleiche Problem mit dem useState-Hook. Noch schlimmer: Der useState-Hook akzeptiert keine Teilaktualisierungen. Daher wurde diese Frage sehr relevant, als useState hook eingeführt wurde.
Ich habe beschlossen, die folgende Antwort zu veröffentlichen, um sicherzustellen, dass die Frage modernere Szenarien abdeckt, in denen der useState-Hook verwendet wird:
Wenn Sie haben:
Sie können die verschachtelte Eigenschaft festlegen, indem Sie die aktuelle Eigenschaft klonen und die erforderlichen Datensegmente patchen. Beispiel:
Oder Sie können die Immer-Bibliothek verwenden, um das Klonen und Patchen des Objekts zu vereinfachen.
Oder Sie können die Hookstate-Bibliothek (Haftungsausschluss: Ich bin Autor) verwenden, um einfach komplexe (lokale und globale) Statusdaten vollständig zu verwalten und die Leistung zu verbessern (lesen Sie: Keine Sorge um die Renderoptimierung):
Holen Sie sich das Feld zu rendern:
Legen Sie das verschachtelte Feld fest:
Hier ist das Hookstate-Beispiel, bei dem der Status tief / rekursiv in einer baumartigen Datenstruktur verschachtelt ist .
quelle
Zwei weitere Optionen, die noch nicht erwähnt wurden:
quelle
Um die Dinge allgemeiner zu gestalten, habe ich an den Antworten von @ ShubhamKhatri und @ Qwerty gearbeitet.
Zustandsobjekt
Eingabesteuerung
updateState-Methode
setState als Antwort von @ ShubhamKhatri
setState als Antwort von @ Qwerty
Hinweis: Diese oben genannten Methoden funktionieren nicht für Arrays
quelle
Ich nehme die bereits geäußerten Bedenken hinsichtlich der Erstellung einer vollständigen Kopie Ihres Komponentenstatus sehr ernst . Vor diesem Hintergrund würde ich Immer dringend empfehlen .
Dies sollte funktionieren
React.PureComponent
(dh flache Zustandsvergleiche durch React), daImmer
ein Proxy-Objekt geschickt verwendet wird, um einen beliebig tiefen Zustandsbaum effizient zu kopieren. Immer ist außerdem typsicherer als Bibliotheken wie Immutability Helper und ideal für Benutzer von Javascript und Typescript.Typescript- Dienstprogrammfunktion
quelle
quelle
obj
es sich nur um einen Hinweis auf den Zustand handelt. Dadurch mutieren Sie das eigentlichethis.state
ObjektIch fand, dass dies für mich funktioniert, da ich in meinem Fall ein Projektformular habe, in dem Sie beispielsweise eine ID und einen Namen haben, und ich lieber den Status für ein verschachteltes Projekt beibehalten möchte.
Gib mir Bescheid!
quelle
So etwas könnte ausreichen,
quelle
Ich weiß, dass es eine alte Frage ist, wollte aber trotzdem mitteilen, wie ich dies erreicht habe. Angenommen, der Status im Konstruktor sieht folgendermaßen aus:
Meine
handleChange
Funktion ist wie folgt:Und stellen Sie sicher, dass Sie die Eingaben entsprechend benennen:
quelle
Ich mache verschachtelte Updates mit einer reduzierten Suche:
Beispiel:
Die verschachtelten Variablen im Status:
Die Funktion:
Verwenden:
quelle
Dies ist mein Anfangszustand
Der Hook oder Sie können ihn durch den Status (Klassenkomponente) ersetzen.
Die Methode für handleChange
Methode zum Festlegen des Status mit verschachtelten Status
Schließlich ist dies die Eingabe, die ich verwende
quelle
Wenn Sie formik in Ihrem Projekt verwenden, gibt es eine einfache Möglichkeit, mit diesen Dingen umzugehen. Hier ist der einfachste Weg, um mit formik umzugehen.
Legen Sie zuerst Ihre Anfangswerte im Attribut formik initivalues oder in der Reaktion fest. Zustand
Hier werden die Anfangswerte im Reaktionszustand definiert
Definieren Sie die obigen Anfangswerte für das formik-Feld innerhalb des formik-
initiValues
AttributsErstellen Sie eine Konsole, um den Status zu überprüfen, in den
string
anstelleboolean
der formik-setFieldValue
Funktion aktualisiert wurde, um den Status festzulegen , oder verwenden Sie das React- Debugger-Tool, um die Änderungen in den formik-Statuswerten anzuzeigen.quelle
Versuchen Sie diesen Code:
quelle
someProperty
flag
Ich sah folgendes in einem Buch:
aber ich bin nicht sicher, ob es richtig ist ..
quelle