Reagieren Sie Suspense: Lehren aus der Datenbelastung von Daten
Suspense ist eine bevorstehende Funktion von React, mit der asynchrone Operationen wie Datenbelastungen koordiniert werden können, wodurch Sie die Verhindern von staatlichen Inkonsistenzen in der Benutzeroberfläche leicht verhindern können. Ich werde ausführlicher erklären, was genau dies bedeutet, und eine kurze Einführung in die Spannung, dann einen realistischeren Anwendungsfall und einige gewonnene Lektionen geben.
Die von mir eingeführten Funktionen befinden sich noch in der Alpha -Stufe und dürfen nicht in Produktionsumgebungen verwendet werden. Dieser Beitrag ist für diejenigen, die den ersten Blick auf die bevorstehenden Funktionen werfen und verstehen möchten, wohin sie in die Zukunft gehen werden.
Einer der herausforderndsten Teile der Anwendungsentwicklung ist die Koordinierung des Anwendungszustands und die Art und Weise, wie Daten geladen werden. Statusänderungen führen normalerweise neue Datenladen an mehreren Stellen aus. In der Regel verfügt jedes Datenstück über eine eigene Lade -Benutzeroberfläche (z. B. einen "Rotator"), der ungefähr dort ist, wo sich die Daten in der Anwendung befinden. Die asynchrone Natur der Datenbelastung bedeutet, dass diese Anforderungen in jeder Reihenfolge zurückgegeben werden können. Infolgedessen erscheint und verschwindet Ihre Anwendung nicht nur mit vielen verschiedenen Spinnern, sondern noch schlimmer, dass Ihre Anwendung möglicherweise inkonsistente Daten anzeigt. Wenn zwei Ihrer drei Datenladungen durchgeführt werden, sehen Sie einen Lastspinner oben in der dritten Position und zeigen immer noch die alten, jetzt veralteten Daten.
Ich weiß, das ist zu viel. Wenn Sie etwas davon verwirrend finden, interessieren Sie sich möglicherweise für einen früheren Artikel über Spannung, den ich geschrieben habe. In diesem Artikel wird detaillierter eingeführt, was Spannung ist und was er implementiert. Beachten Sie timeoutMs
dass einige dieser kleinen Details jetzt veraltet sind, d useTransition
H.
Schauen wir uns nun die Details kurz an und gehen Sie dann zu einem bestimmten Anwendungsfall mit einigen lauernden Fallen über.
Glücklicherweise ist das React -Team intelligent genug, um diese Bemühungen nicht nur zu begrenzen, nur Daten zu laden. Die Spannung arbeitet durch Grundelemente auf niedrigem Niveau, die Sie auf fast alles anwenden können. Schauen wir uns diese Primitiven kurz an.
Erstens<suspense></suspense>
Grenze akzeptiert es ein fallback
-Attribut:
<suspense fallback="{<Fallback"></suspense> }>
Immer wenn Kinderkomponenten unter dieser Komponente hängen, macht es fallback
. Unabhängig davon, wie viele Unterkomponenten aus irgendeinem Grund suspendiert werden, wird fallback
angezeigt. Dies ist eine Möglichkeit, wie React sicherstellt, dass die Benutzeroberfläche konsistent ist - sie rendert nichts, bis alles fertig ist.
Aber was passiert, wenn der Benutzer den Status ändert und neue Daten lädt, nachdem der Inhalt ursprünglich gerendert wurde? Wir möchten nicht, dass unsere vorhandene Benutzeroberfläche verschwindet und unseren fallback
zeigt. Stattdessen möchten wir vielleicht einen Ladespinner anzeigen, bis alle Daten vor der Anzeige der neuen Benutzeroberfläche fertig sind.
Der useTransition
-Haken implementiert dies. Dieser Haken gibt eine Funktion und einen booleschen Wert zurück. Wir nennen die Funktion und wickeln unsere Zustandsänderungen ein. Jetzt werden die Dinge interessant. React versucht, unsere Statusänderungen anzuwenden. Wenn irgendetwas hängt, setzt React den Booleschen Wert auf true
und wartet auf das Ende des Aufhängens. Sobald es fertig ist, wird versucht, die Statusänderung erneut anzuwenden. Vielleicht wird es diesmal erfolgreich sein, oder vielleicht hängt etwas anderes. Wie auch immer, die Boolesche Flagge bleibt true
, bis alles fertig ist und erst dann die staatliche Änderung abgeschlossen und in der Benutzeroberfläche widerspiegelt.
Wie hängen wir schließlich? Wir hängen, indem wir ein Versprechen werfen. Wenn die Daten angefordert werden und wir holen müssen, holen wir uns ein - und werfen ein Versprechen, das mit diesem Fetch zusammenhängt. Dieser Mechanismus auf niedriger Ebene bedeutet, dass wir ihn für alles verwenden können. Das React.lazy
-Dienstprogramm für faule Ladekomponenten funktioniert bereits mit Spannung, und ich habe vor der Suspense geschrieben, um auf das Laden des Bildes zu warten, bevor die Benutzeroberfläche angezeigt wird, um zu verhindern, dass sich Inhalte bewegen.
Mach dir keine Sorgen, wir werden all das besprechen.
Wir werden etwas anderes als die Beispiele in anderen ähnlichen Artikeln aufbauen. Denken Sie daran, dass die Spannung noch in der Alpha -Phase liegt, sodass Ihr bevorzugtes Ladedatendienstprogramm noch keine Suspense -Unterstützung bietet. Das heißt aber nicht, dass wir etwas nicht vortäuschen und verstehen können, wie Spannung funktioniert.
Erstellen wir eine unendliche Ladeliste, in der einige Daten angezeigt werden und einige vorinstallierte Bilder basierend auf der Spannung kombiniert. Wir werden unsere Daten sowie eine Schaltfläche anzeigen, um mehr Daten zu laden. Wenn die Daten gerendert werden, werden wir das zugehörige Bild vorladen und hängen, bevor es fertig ist.
Dieser Anwendungsfall basiert auf den tatsächlichen Arbeiten, die ich in meinem Nebenprojekt geleistet habe (verwenden Sie wieder keine Spannung in der Produktion, aber das Nebenprojekt ist erlaubt). Ich habe damals meinen eigenen GraphQL -Client verwendet und die Motivation für diesen Beitrag waren einige der Schwierigkeiten, die ich hatte. Um den Vorgängen zu vereinfachen und sich auf die Suspense selbst zu konzentrieren, anstatt sich auf einzelne Datenbelastungsunternehmen zu befinden, werden wir nur das Laden von Daten schmieden.
Dies ist der Sandkasten, den wir ursprünglich ausprobiert haben. Wir werden es verwenden, um alles Schritt für Schritt zu erklären, sodass es nicht erforderlich ist, den gesamten Code jetzt zu verstehen.
Unsere Root App
-Komponente macht eine solche Spannungsgrenze wie diese:
<suspense fallback="{<Fallback"></suspense> }>
fallback
rendert immer dann, wenn etwas hängt (es sei denn, die Zustandsänderung tritt im useTransition
-Anruf auf). Um die Dinge zu verstehen, habe ich diese Fallback
Komponente dazu gebracht, das gesamte UI-Rosa zu machen, also ist es schwer zu übersehen.
Wir laden den aktuellen Datenblock in DataList
:
const newdata = useQuery (param);
Unser useQuery
-Hook ist hartcodiert, um gefälschte Daten zurückzugeben, einschließlich eines Zeitlimits für simulierte Netzwerkanforderungen. Es kümmert sich um zwischengespeicherte Ergebnisse und verspricht, wenn die Daten nicht zwischengespeichert werden.
Wir speichern den Status (zumindest vorerst) in der Hauptdatenliste, die wir anzeigen:
const [data, setData] = usustate ([]);
Wenn neue Daten aus unserem Haken übergeben werden, fügen wir sie an unsere Hauptliste hinzu:
useEffect (() => { setData ((d) => d.concat (newdata)); }, [newdata]);
Wenn der Benutzer mehr Daten benötigt, klicken er auf die Schaltfläche, die diese Funktion aufruft:
Funktion loadmore () { starttransition (() => { setParam ((x) => x 1); }); }
Beachten Sie schließlich, dass ich die SuspenseImg
-Komponente verwende, um die Vorspannung des Bildes zu verarbeiten, das ich mit jedem Datenstück zeige. Es werden nur fünf zufällige Bilder angezeigt, aber ich habe eine Abfragezeichenfolge hinzugefügt, um sicherzustellen, dass für jedes neue Daten, dem wir begegnen, neue Ladungen erstellt werden.
Um zusammenzufassen, wo wir gerade sind, haben wir einen Haken, der die aktuellen Daten lädt. Dieser Haken folgt dem Spannungsmechanismus und macht beim Laden ein Versprechen. Wenn sich diese Daten ändert, wird die Gesamtliste der laufenden Projekte aktualisiert und neue Projekte beigefügt. Dies geschieht in useEffect
. Jedes Projekt macht ein Bild. Wir verwenden die SuspenseImg
-Komponente, um das Bild vorzuladen und zu hängen, bevor es fertig ist. Wenn Sie neugierig sind, wie ein Code funktioniert, lesen Sie meinen vorherigen Beitrag zu Vorspannungsbildern mit Spannung.
Wenn alles gut funktioniert, ist dies ein sehr langweiliger Blog -Beitrag, mach dir keine Sorgen, es ist nicht normal. Beachten Sie, dass der Pink- fallback
-Bildschirm angezeigt und dann bei der ersten Last schnell versteckt wird, aber dann erneut eingestellt wird.
Wenn wir auf die Schaltfläche klicken, um weitere Daten zu laden, sehen wir, dass die Inline -Lastanzeige (gesteuert vom useTransition
Hook) auf true
flip. Dann sehen wir, dass es zu false
ist, und unsere ursprünglichen rosa fallback
-Displays. Wir erwarten, dass der rosa Bildschirm nach der anfänglichen Last nicht mehr sieht. was ist passiert?
Es wurde an einem auffälligen Ort versteckt:
useEffect (() => { setData ((d) => d.concat (newdata)); }, [newdata]);
useEffect
läuft, wenn die Zustandsänderung abgeschlossen ist, d. H. Die Zustandsänderung wurde gehängt und auf das DOM angewendet. Dieser Teil, der "abgeschlossen" ist, ist hier der Schlüssel. Wir können den Staat hier einstellen, wenn wir wollen, aber wenn diese staatliche Änderung wieder hängt, ist es ein brandneuer Hang. Aus diesem Grund sehen wir, wie Pink nach der anfänglichen Belastung und den nachfolgenden Datenbelastungen blinkt. In beiden Fällen erfolgt die Datenbelastung und wir setzen dann den Zustand in einen Effekt, wodurch die neuen Daten tatsächlich wiedergegeben und hängen, weil das Bild vorinstalliert ist.
Wie lösen wir dieses Problem? Auf einer Ebene ist die Lösung einfach: Hören Sie auf, den Zustand in den Effekt festzulegen. Aber das ist leichter gesagt als getan. Wie aktualisieren wir die Liste der laufenden Einträge, um neue Ergebnisse ohne Effekte anzuhängen? Sie denken vielleicht, wir können Ref verwenden, um Dinge zu verfolgen.
Leider bringt Suspense einige neue Regeln für Refs mit, das heißt, wir können Refs nicht in das Render einstellen. Wenn Sie sich fragen, warum, denken Sie daran, dass es bei der Spannung darum geht, zu versuchen, das Render zu führen, das Versprechen zu sehen, und dann diesen Rendern zu verwerfen. Wenn wir den Schiedsrichter ändern, bevor das Rendering abgesagt und verworfen wird, hat der Schiedsrichter immer noch diese Änderung, hat jedoch einen ungültigen Wert. Die Rendering -Funktion muss rein sein und hat keine Nebenwirkungen. Dies war schon immer eine Regel für React, aber jetzt ist es wichtiger.
Dies ist die Lösung, wir werden den Absatz nach Absatz erklären.
Anstatt unsere Hauptdatenliste im Staat zu speichern, tun Sie zunächst etwas anderes: Speichern wir die Liste der Seiten, die wir anzeigen. Wir können die neueste Seite im Schiedsrichter speichern (obwohl wir sie nicht in das Render schreiben werden) und eine Reihe aller aktuell geladenen Seiten im Bundesstaat speichern.
const currentPage = useref (0); const [Seiten, SetPages] = Usestate ([currentPage.current]);
Um weitere Daten zu laden, werden wir entsprechend aktualisieren:
Funktion loadmore () { starttransition (() => { currentPage.current = currentPage.current 1; SetPages ((Seiten) => Seiten.Concat (currentPage.current)); }); }
Der schwierige Teil ist jedoch, wie diese Seitenzahlen in tatsächliche Daten umwandelt werden. Was wir nicht tun können, ist, diese Seiten zu durchlaufen und unseren useQuery
-Haken aufzurufen. Wir brauchen eine neue, nicht leitende Daten-API. Nach der sehr inoffiziellen Konvention, die ich in meinen früheren Spannungsdemos gesehen habe, habe ich diese Methode read()
benannt. Es wird kein Haken sein. Wenn die Daten zwischengespeichert werden, wird die angeforderten Daten zurückgegeben, sonst wird ein Versprechen geworfen. Für unsere gefälschten Datenladen -Haken bestand ich nicht nötig, um echte Änderungen vorzunehmen. Für die tatsächliche Datenbelastung der Versorgungsbibliothek kann der Autor jedoch einige Arbeit benötigen, um beide Optionen im Rahmen seiner öffentlichen API aufzudecken. Im GraphQL -Client, den ich zuvor erwähnt habe, gibt es in der Tat sowohl den useSuspenseQuery
-Hook als auch read()
-Methode im Client -Objekt.
Mit dieser neuen read()
-Methode ist der letzte Teil unseres Codes trivial:
const data = pages.flatmap ((Seite) => read (Seite));
Wir nehmen jede Seite und fordern die entsprechenden Daten mit unserer read()
-Methode an. Wenn keine Seite zwischengespeichert wird (es sollte tatsächlich nur die letzte Seite in der Liste sein), wird ein Versprechen geworfen und React für uns hängt. Wenn Promise Parse spielt, wird React die vorherige Änderung des Status erneut ausprobieren, und dieser Code wird erneut ausgeführt.
Lassen Sie sich nicht von flatMap
anrufen. Es ist genau das Gleiche wie die map
, außer dass es jedes Ergebnis in das Neue Array erzielt und sie "flach", wenn es selbst ein Array ist.
Bei diesen Änderungen funktioniert alles wie erwartet. Unser rosa Ladebildschirm wird einmal bei anfänglicher Last angezeigt, und dann wird der Inline -Ladestatus im anschließenden Laden angezeigt, bis alles fertig ist.
Spannung ist ein aufregendes Update, um zu reagieren. Es befindet sich immer noch in der Alpha -Phase. Versuchen Sie also nicht, es für etwas Wichtiges zu verwenden. Wenn Sie jedoch ein Entwickler sind, der gerne den ersten in den kommenden Inhalten erlebt, hoffe ich, dass dieser Beitrag Ihnen einen nützlichen Hintergrund und Informationen bietet, die bei der Veröffentlichung nützlich sein werden.
Das obige ist der detaillierte Inhalt vonReagieren Sie Suspense: Lehren beim Laden von Daten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!