Redux: Warum kann Zustand nicht mutiert werden ....

Erstellt am 20. Sept. 2015  ·  13Kommentare  ·  Quelle: reduxjs/redux

Hallo,

Ich lese mit Interesse über unveränderliche und wie Sie Ihren Zustand nicht mutieren sollten. Ich verstehe bis zu einem gewissen Grad, warum das so ist, aber die Seite "besorgt über die Zeit, die ich für das Erstellen neuer Objekte aufgewendet habe" versteht entweder nicht in JS, wie schnell / langsam dies ist, oder ich vermisse etwas anderes.

Normalerweise scheint es mir zeitaufwändiger zu sein, ein neues Objekt zu erstellen, ein altes Objekt mehr oder weniger in das neue zu klonen und die neuen Statusadditionen (oder -subtraktionen) hinzuzufügen, als nur den vorhandenen Status zu ändern. Also versuche ich zu verstehen, warum das Unveränderliche so wichtig ist und wirkt es sich auf etwas anderes in der Kette aus, das ich einfach nicht sehe?

Außerdem würde ich denken, dass vieles, was Reduct bietet, dem Reaktionskern hinzugefügt werden könnte und vielleicht sogar die DOM-Diffing-Engine nutzen könnte ... vielleicht sogar, um festzustellen, ob der Zustand mutieren sollte oder nicht. Ich bin nicht sicher, ob der Prozess des Mutierens des Zustands schneller oder langsamer wäre, als den Status mit dem neuen Status zu unterscheiden und nur die Teile des tatsächlichen Statusobjekts zu ändern (mutieren), die sich ändern sollten.

Ich bin relativ neu in all dem, also vergib mir, wenn mir etwas fehlt, was den Gedanken betrifft, den Zustand nicht zu mutieren. Ich mag die Idee, dass Komponenten nur unveränderliche Daten rendern sollten ... aber andererseits ist es der Komponente egal oder sie weiß nicht, ob sie unveränderlich ist oder nicht ... es sind nur Daten, die von irgendwoher weitergegeben werden, also habe ich Probleme mit a Bit mit dem ganzen unveränderlichen vs veränderlichen Zustand.

question

Hilfreichster Kommentar

Nur um zu verdeutlichen: Der Staat wird nicht bei jeder Handlung tief geklont. Nur die Teile, die sich geändert haben, werden geklont (wiederum nicht tief - hängt davon ab, was geändert wurde). Wenn beispielsweise eine Aufgabe in der TodoMVC-App bearbeitet wird, wird nur dieses Aufgabenobjekt geklont. Die restlichen Aufgabenobjekte sind gleich. Natürlich wird ein neues Root-Aufgabenlisten-Array erstellt, das auf das neue Objekt verweist, aber die Objekte selbst werden nicht geklont, wenn sie nicht geändert wurden. Daher ist es nicht so teuer, wie es scheint. Wenn es teuer wird (z. B. schnelle Array-Änderungen), können Sie außerdem eine Bibliothek wie Immutable.js verwenden, die dank struktureller Freigabe sehr schnell kopiert werden kann. Mit Immutable.js ist das Kopieren selbst großer Arrays nicht wirklich so teuer, da große Teile des Speichers wiederverwendet werden. Unabhängig davon, ob mit oder ohne Immutable.js, hilft uns die Unveränderlichkeit dabei, die App effizient neu zu rendern, da wir wissen, was sich genau geändert hat, da die Objekte nicht mutiert sind.

Alle 13 Kommentare

Es geht um Vorhersehbarkeit und Zuverlässigkeit.

Reduktionsmittel in Redux sind reine Funktionen, was bedeutet, dass sie keine Nebenwirkungen haben. Sobald Sie einen externen Zustand dieser Funktionen betrachten, sind sie nicht mehr rein. Und wenn sie nicht rein sind, können sie unzuverlässig sein. Und das verursacht Fehler, von denen viele sehr schwer zu finden sein können.

Ich habe durch das Schreiben reiner Funktionen festgestellt, dass ich weniger Fehler in meinem Code produziere und produktiver bin. Das Nachladen von heißen Modulen (ermöglicht durch die Verwendung reiner Funktionen) ist ein Turbolader, der über diese Produktivität hinausgeht.

Und Sie erhalten kostenlos Funktionen wie Zeitreisen, die sehr praktisch sind.

Schließen als Duplikat von # 328.

Nur um zu verdeutlichen: Der Staat wird nicht bei jeder Handlung tief geklont. Nur die Teile, die sich geändert haben, werden geklont (wiederum nicht tief - hängt davon ab, was geändert wurde). Wenn beispielsweise eine Aufgabe in der TodoMVC-App bearbeitet wird, wird nur dieses Aufgabenobjekt geklont. Die restlichen Aufgabenobjekte sind gleich. Natürlich wird ein neues Root-Aufgabenlisten-Array erstellt, das auf das neue Objekt verweist, aber die Objekte selbst werden nicht geklont, wenn sie nicht geändert wurden. Daher ist es nicht so teuer, wie es scheint. Wenn es teuer wird (z. B. schnelle Array-Änderungen), können Sie außerdem eine Bibliothek wie Immutable.js verwenden, die dank struktureller Freigabe sehr schnell kopiert werden kann. Mit Immutable.js ist das Kopieren selbst großer Arrays nicht wirklich so teuer, da große Teile des Speichers wiederverwendet werden. Unabhängig davon, ob mit oder ohne Immutable.js, hilft uns die Unveränderlichkeit dabei, die App effizient neu zu rendern, da wir wissen, was sich genau geändert hat, da die Objekte nicht mutiert sind.

Ahh ... sehen Sie, dass das letzte Bit jetzt Sinn macht ... Ich gehe davon aus, dass Sie damit sagen, dass aufgrund der Änderung des Komponenten-Renderings aufgrund nur des geänderten Status die React Diff / Redraw-Engine dadurch schneller ist? Ähnlich denke ich sollte shouldComponentUpdate

Ich gehe davon aus, dass Sie damit sagen, dass aufgrund der Änderung des Komponenten-Renderings aufgrund nur des geänderten Status die React Diff / Redraw-Engine dadurch schneller ist. Ähnlich denke ich sollte shouldComponentUpdate

Genau, react-redux verwendet dank der Unveränderlichkeitsgarantie ein aggressives shouldComponentUpdate unter der Haube.

@gaearon Tut nekrotisieren ! aber Ihr Kommentar zu schnellen Array-Updates:

Wenn es teuer wird (z. B. schnelle Array-Änderungen), können Sie außerdem eine Bibliothek wie Immutable.js verwenden, die dank struktureller Freigabe sehr schnell kopiert werden kann.

Ich möchte Redux für die Aktualisierung eines Arrays mit bis zu 8000 Positionen verwenden und erwarte, dass der Durchsatz im Bereich von 10 bis 100 Änderungen pro 100 ms liegt. Kämpfe ich einen verlorenen Kampf, um zu versuchen, den Staat mit Redux auf diese Weise zu verwalten?
Wir planen, den Status eher über eine Leinwand als über das DOM darzustellen, aber ich würde gerne verstehen, ob die Häufigkeit von Aktualisierungen Ihrer Erfahrung nach ein Problem verursachen würde oder nicht.

@dougajmcdonald : Meine erste Frage ist, kann irgendetwas von dieser Arbeit auf irgendeine Weise zusammengefasst werden? Müssen Sie wirklich jedes einzelne Update als separate Neuzeichnung der Benutzeroberfläche darstellen?

Darüber hinaus würde ich vorschlagen, dass Sie sich diese Ressourcen zur Leistung im Zusammenhang mit Redux ansehen:

Gerne unterhalte ich mich auch in den

@markerikson Leider beinhaltet das Konzept des Spiels viele schnelle Aktualisierungen einer relativ großen Datenstruktur.
Mir ist klar, dass ich in meinem ursprünglichen Kommentar nicht ganz klar war. Wenn ich 10-100 Änderungen sage, würden diese nicht alle Neuzeichnungen auslösen. Die 10-100 Änderungen sind die Statusänderungen, die durch ein einzelnes Neuzeichnen pro 100 ms dargestellt würden.
Meine Frage ist also wirklich, wenn ich meine Aktualisierungen auf 10-100 Statusänderungen pro 100 ms stapeln würde, wäre das Statusmanagement innerhalb von redux in der Lage, diese effektiv auf eine Weise zu verarbeiten, die innerhalb eines 100 ms-ähnlichen Fensters sinnvoll abgeschlossen werden würde Erlaube ein Neuzeichnen, ohne dass Dinge zurückbleiben.
Die Statusaktualisierungen würden im Wesentlichen das Ändern von 3-4 Eigenschaften in einem Array der Größe 8000 beinhalten. Wir würden also über das Erstellen eines neuen Arrays 1-10 Mal pro ms sprechen (vorausgesetzt, wir möchten die Dinge unveränderlich halten), wobei einige Änderungen an einer der Eigenschaften vorgenommen werden die Objekte innerhalb des Array-Index. Die Objekte sind ziemlich klein (3-4 Eigenschaften, ein paar Zahlen und ein paar kleine Zeichenketten)

Aus diesem Grund habe ich mich über die Vorteile der Verwendung von unveränderlichen Daten gewundert, wie von Dan vorgeschlagen, als ob wir so viel Array wie möglich wiederverwenden könnten. Dies würde wahrscheinlich die Leistung verbessern.

@dougajmcdonald :

Immutable.js ist keine magische, die Perfektion verbessernde Silberkugel. Es kann einige Dinge schneller und andere langsamer machen. Ich habe mehrere Artikel über Immutable.js-bezogene Perf-Überlegungen, die Sie sich vielleicht ansehen möchten.

Um ehrlich zu sein, könnten Sie angesichts Ihres Anwendungsfalls theoretisch mehr mit direkter Mutation davonkommen, wenn Sie wollten. Gemäß meinem Beitrag Idiomatic Redux, Teil 1 - Implementierung und Absicht , kümmert sich der Redux-Kern selbst überhaupt nicht um Mutationen - es ist in erster Linie die React-Redux-UI-Schicht, die dies tut, sowie die DevTools. Nun, Mutation ist nicht die Art und Weise, wie Sie Redux verwenden wollen, aber es ist möglich.

Mein persönlicher Rat wäre, einfach anzufangen. Verwenden Sie einfach einfache JS-Objekte und Arrays. Aktualisieren Sie sie unveränderlich, entweder "von Hand" oder mithilfe einer der vielen verfügbaren Bibliotheken für

Von dort aus können Sie dann zusätzliche Optimierungsarbeiten in Bezug auf das Stapeln, das Reduzieren von Versendungen, das Aktualisieren der Logik usw. durchführen.

@markerikson subtile Halse auf die Nase genommen! : p Ja, Sie haben Recht. Die Reduktionsseite der Dinge im Moment ist im Grunde die Schaffung und Zerstörung eines ziemlich großen Arrays, aber ich denke, das eigentliche Problem ist eher die Reaktion auf den Lebenszyklus von Komponenten, wenn das Endziel sein wird Ein Canvas-Element, das idealerweise mit 60ish FPS gerendert wird.
Vielen Dank für den Punkt über unveränderliche und die Punkte über direkte Mutation. Ich werde ein wenig nachlesen und auch diese berücksichtigen.
Im Moment besteht mein Denkprozess darin, den Redux-Status von der Leinwand zu trennen und Nachrichten einfach über Pub / Sub (so haben wir es bereits angeschlossen) an ihn weiterzuleiten, nur mit mehr beweglichen Teilen

Ich denke darüber nach, mich zu ändern von:
pubsub> dispatch ()> reducer> redux state> reagiere auf komponentenmaterial> canvas render.

Zu:
pubsub> lokaler Komponentenstatus> Canvas-Rendering

Ich werde weiterhin Redux für den Rest der Benutzeroberfläche verwenden, nur vielleicht nicht für den Canvas-Teil der App.

Ihre Fragen sind absolut gültig. Tatsächlich funktioniert die vuejs-Implementierung von Redux namens vuex unter dem Konzept der Mutation. Die 'Reduzierer' werden also tatsächlich Mutationen genannt, und solange Sie den Zustand an einem zentralen Ort ändern, sollte alles in Ordnung sein. Dies geschieht, weil vue dem Status der App Beobachter und andere Dinge hinzufügt. Wie Sie bereits erwähnt haben, ist es im Fall von vue sinnvoller, das Objekt zu ändern, als es zu ersetzen. Redux ist unveränderlich und am Ende reagiert die Leistung beider Ansätze auf VS Vue Virtual DOM-Updates meistens gleich an dem Punkt, an dem nicht gesagt werden kann, dass in allen Fällen einer besser ist als der andere

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen