Theo hat diese Woche ein Video über unintuitives Verhalten von React-Hooks gemacht und dabei insbesondere die Idee eines Hooks namens usePrevious untersucht, um die Wertversion des letzten Re-Renderings vor dem aktuellen zu behalten eins. Eine Möglichkeit, eine Logik mit dem alten und dem neuen Zustand herzustellen.
Wenn Sie Ideen zur Umsetzung sehen möchten, schauen Sie sich bitte das Video an. In diesem Beitrag geht es darum, den konzeptionellen Aspekt eines Hooks wie usePrevious zu erkunden.
Wie Sie sehen können, haben wir in React keinen solchen primitiven Hook. Vor Hooks, im klassenbasierten Zeitalter, hatten wir eine Lebenszyklusmethode namens „componentDidUpdate“, bei der wir alle vorherigen Status und Requisiten als Parameter bekamen. Warum haben sie dieses Verhalten nicht bei Hooks beibehalten?
Es kann ein wenig eintönig sein, wenn Sie diese Beitragsreihe lesen, aber in diesem Fall müssen wir über den Paradigmenwechsel sprechen.
Bei Klassen gibt es bei der Aktualisierung einiger Zustände keine automatische Möglichkeit, die abgeleiteten Werte neu zu berechnen. Wenn Sie bestimmte Requisiten und Zustände verwenden, um einen neuen Wert zu berechnen, müssen Sie selbst überprüfen, ob sich einige davon geändert haben.
Auf diese Weise besteht die Lösung darin, einen Rückruf zu haben, der bei allen Aktualisierungen aufgerufen wird, und dem Benutzer die vorherigen Werte zu senden. Der App-Code prüft die Unterschiede und aktualisiert den berechneten Zustand mit dem neuen Ergebnis. Dies liegt an der Direktheit klassenbasierter Komponenten. Sie haben die vollständige Kontrolle über den Datenfluss und müssen die Berechnungen manuell steuern.
Hier kommen wir zu Reaktivitätsausdrücken.
Anstatt die Änderung überprüfen und durchführen zu müssen, schreiben Sie einen Ausdruck, sozusagen die Berechnungsformel. Diese Berechnung muss mit der aktuellen Statusversion ausgeführt werden, ohne Zugriff auf die vorherige.
Stellen Sie sich eine Formel vor:
a = b + c b = 10 c = 20 a = 10 + 20 a = 30
Wenn ich diesen Ausdruck 1 Million Mal verwende und dabei b als 10 und c als 20 übergebe, erhalte ich das gleiche Ergebnis. Das ist eine reine Berechnung. React führt das gleiche Prinzip aus. Alle Ableitungsberechnungen sollten rein sein.
Aber warum ist es wichtig?
Reagieren Sie auf die Arbeit beim erneuten Rendern. Jeder Zyklus generiert eine Beschreibung der Benutzeroberfläche und schreibt basierend auf den Unterschieden zwischen dem aktuellen und dem nächsten Zyklus Änderungen in das DOM. Jedes Rendering ist vollständig vom vorherigen oder nächsten getrennt.
UI = fn(state)
Für jede unterschiedliche Statusversion haben wir also eine andere UI-Version. Das wird ziemlich verwirrend, wenn wir hier frühere Werte hinzufügen. Denn nun kommt es nicht nur auf den Zustand an, sondern auch auf den previousState. Anstatt eine Quelle, einen Ausdruck und ein Ergebnis zu haben, kann ich mehrere Quellen haben, möglicherweise komplexere Ausdrücke, um diese Quellen zu verarbeiten, und als Ergebnis eine inkonsistente und unvorhersehbare Benutzeroberfläche.
Jedes Rendering verhält sich basierend auf dem vorherigen Status anders. Und da einige der möglichen Implementierungen von usePrevious auf der Zeitreihenfolge in React basieren, wird dies gefährlicher.
Mit gleichzeitigen Funktionen kann React ein Rendern ohne Vorwarnung stoppen, um andere Aktionen zu priorisieren. Abhängig von useEffect und ref können Sie eine veraltete Version eines „vorherigen“ Renderings behalten, die sogar die echte vorherige ist. Noch mehr Chaos, über das man nachdenken kann.
Denken Sie in einem Ausdruck wie diesem
a = b + c b = 10 c = 20 a = 10 + 20 a = 30
Ein Teil davon hat Priorität und muss vorher berechnet werden, denken wir es uns mit Javascript-Code:
UI = fn(state)
Jetzt haben wir also zwei getrennte Ausdrücke, die separat berechnet werden können und vollkommen rein sind. Aber wie können wir das Problem lösen, wenn sich der Wert von b stark ändert und die Berechnung für cdResult teuer ist? Auswendiglernen!
a = b + (c - d)
Jetzt wird cdResult nur dann neu berechnet, wenn sich c oder d ändert.
Aber oben im Text habe ich gesagt, dass es keinen vorherigen Wert gibt, aber wie kann eine Berechnung eines Renders im nächsten verwendet werden? Das beeinträchtigt nicht die Reinheit der Berechnungen?
Eigentlich nein. Zum Beispiel:
const cdResult = c - d; const a = b + cdResult;
Stellen Sie sich vor, wir befinden uns im Render Nummer 1. Das c hat den Wert 30 und d den Wert 20, das Ergebnis ist also 10. Aber während ich es mir merke, behält React die von mir hinzugefügten Abhängigkeiten im Auge das Array. Wenn sich einige davon ändern, erfolgt eine Neuberechnung.
const cdResult = React.useMemo(() => c - d, [c, d]); const a = b + cdResult;
Aber sie haben sich nicht verändert. Wenn ich diesen Ausdruck erneut aufrufe, mit c als 30 und d als 20, erhalte ich als Ergebnis dasselbe 10. Obwohl ich mich im Render Nummer 2 befinde und sich andere Variablen geändert haben, haben sich die Abhängigkeiten, die ich in dieser Berechnung verwende, nicht geändert.
Ich kann es bei jedem Rendern erneut berechnen, das ist das Standardverhalten von React, aber ich kann eine unnötige Neuberechnung überspringen, die denselben Wert zurückgibt, also habe ich ihn beibehalten. Wir haben die Reinheit beibehalten und die Trennung zwischen den Renderings beibehalten
Aber es gibt einen guten Ort, um Logik mit vorherigen Status- und Benutzeraktionen zu erstellen. Natürlich wäre das in dem Moment, in dem der Rückruf aufgerufen wird, der aktuelle Zustand. Aber wenn Sie einen Zustand haben, der sich aufgrund einer Logik ändern muss, dann ist das der richtige Ort.
Natürlich kann es sehr spezielle Fälle geben, in denen Sie möglicherweise einen Hook wie „usePrevious“ benötigen, aber seien Sie sich der Inkonsistenzen bewusst, die dadurch verursacht werden können, und versuchen Sie, Garantien hinzuzufügen, um Fehler in der Anwendung zu vermeiden.
Und was noch wichtiger ist: Vermeiden Sie es, wenn möglich.
Das obige ist der detaillierte Inhalt vonDas Problem mit usePrevious und ähnlichen zeitorientierten Hooks. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!