Reagieren Sie in der Praxis Spannung
In diesem Artikel wird der Arbeitsmechanismus, die Funktionalität von React -Spannung und die Integration in reale Webanwendungen untersucht. Wir werden lernen, wie man Routing und Datenbelastung mit Spannung in React integriert. Zum Routing werde ich native JavaScript verwenden und meine eigene Micro-Graphql-Reaktions-GraphQL-Bibliothek für die Datenverarbeitung verwenden.
Wenn Sie in Betracht ziehen, React Router zu verwenden, sieht es gut aus, aber ich hatte nie die Chance, ihn zu verwenden. Mein persönliches Projekt hat eine einfache Routing -Lösung, die ich immer manuell gemacht habe. Die Verwendung natives JavaScript bietet uns außerdem ein besseres Verständnis dafür, wie Spannung funktioniert.
Kurzer Hintergrund
Sprechen wir über Spannung selbst. Kingsley Silas gibt einen umfassenden Überblick darüber, aber das erste, was zu beachten ist, ist, dass es sich immer noch um eine experimentelle API handelt. Dies bedeutet - und die Dokumentation von React sagt dies nicht für die Arbeit in einer Produktionsumgebung. Es kann sich jederzeit ändern, bis es vollständig abgeschlossen ist. Denken Sie also daran.
Das heißt, der Kern der Spannung liegt in der Aufrechterhaltung einer konsistenten Benutzeroberfläche, wenn asynchrone Abhängigkeiten (z. B. faule Lade -React -Komponenten, GraphQL -Daten usw.). Suspense bietet APIs auf niedrigem Niveau, mit denen Sie die Benutzeroberfläche einfach verwalten können, wenn Ihre Anwendung diesen Inhalt verwaltet.
Aber was bedeutet in diesem Fall "konsistent"? Dies bedeutet, dass die teilweise abgeschlossene Benutzeroberfläche nicht gerendert wird . Dies bedeutet, dass, wenn es drei Datenquellen auf der Seite gibt, von denen eine abgeschlossen ist, wir das aktualisierte Zustandsfragment und die Lastanzeigen für die beiden anderen veralteten Zustandsfragmente daneben nicht rendern möchten.
Was wir tun möchten , ist dem Benutzer anzugeben, dass die Daten geladen werden, während wir weiterhin die alte Benutzeroberfläche angezeigt oder eine alternative Benutzeroberfläche anzeigen, um anzuzeigen, dass wir auf die Daten warten. Suspense unterstützt beide, die ich später detaillierter eingehen werde.
Die genaue Funktion der Spannung
Dies ist viel einfacher als es scheint. In React haben Sie traditionell den Status festgelegt und Ihre Benutzeroberfläche wird aktualisiert. Das Leben ist einfach. Es führt aber auch zu Inkonsistenzen in den oben genannten Typen. Suspense fügt eine Funktion hinzu, mit der die Komponente reagieren kann, wenn sie auf asynchrone Daten wartet. Dies wird als Hang bezeichnet, der überall im Komponentenbaum passieren kann und bei Bedarf mehrmals auftreten kann, bis der Baum fertig ist. Wenn eine Komponente hängt, weigert sich React, das suspendierte Status -Update zu machen, bis alle ausstehenden Abhängigkeiten erfüllt sind.
Was passiert also, wenn die Komponente suspendiert wird? React schaut den Baum hoch und findet den ersten<suspense></suspense>
Komponente und machen seinen Fallback -Inhalt. Ich werde viele Beispiele angeben, aber vorerst wissen Sie bitte, dass Sie Folgendes angeben können:
<suspense fallback="{<Loading"></suspense> }>
……Wenn<suspense></suspense>
Alle Kinderkomponenten des Hangs werden gerendert<loading></loading>
Komponenten.
Aber was passiert, wenn wir bereits eine gültige, konsistente Benutzeroberfläche haben und der Benutzer neue Daten lädt, was dazu führt, dass die Komponente hängt? Dies führt dazu, dass die gesamte vorhandene Benutzeroberfläche nicht enthält und den Fallback -Inhalt darstellt. Dies ist immer noch konsistent, aber keine gute Benutzererfahrung. Wir möchten lieber, dass die alte Benutzeroberfläche auf dem Bildschirm bleibt, wenn neue Daten geladen werden.
Um dies zu unterstützen, bietet React eine zweite API, useTransition
, die effektiv Zustandsänderungen im Gedächtnis erfolgt. Mit anderen Worten, Sie können den Zustand im Speicher festlegen und gleichzeitig die vorhandene Benutzeroberfläche auf dem Bildschirm aufbewahren. Reagieren Sie buchstäblich eine zweite Kopie des Komponentenbaums im Speicher und legt den Zustand auf diesem Baum fest. Die Komponente kann hängen, aber nur im Speicher hängt, sodass Ihre vorhandene Benutzeroberfläche weiterhin auf dem Bildschirm angezeigt wird. Wenn die Zustandsänderung abgeschlossen ist und die gesamte ausstehende Lösung aufgelöst wird, wird die Zustandsänderung des Speichers auf den Bildschirm gerendert. Offensichtlich möchten Sie dem Benutzer im Vorgang Feedback geben, sodass useTransition
einen pending
booleschen Wert bietet, mit dem Sie eine Art Inline -Lastbenachrichtigung anzeigen können, während Sie die anstehende im Speicher auflösen.
Wenn Sie es in Betracht ziehen, möchten Sie möglicherweise keine vorhandene Benutzeroberfläche auf unbestimmte Zeit anzeigen, wenn die Last suspendiert wird. Wenn der Benutzer versucht, etwas auszuführen und eine lange Zeit vergangen ist, bevor es fertig ist, sollten Sie wahrscheinlich in Betracht ziehen, dass die vorhandene Benutzeroberfläche veraltet und ungültig ist. Zu diesem Zeitpunkt möchten Sie möglicherweise , dass Ihr Komponentenbaum hängen und anzeigen kann<suspense></suspense>
Inhalt zurückspulen.
Um dies zu erreichen, nimmt die useTransition
den timeoutMs
. Dies bedeutet, dass Sie bereit sind, den In-Memory-Zustand für die Zeit vor dem Aufhängen zu verändern zu lassen.
const component = props => { const [startTransition, iSpending] = Usetransition ({Timeouts: 3000}); // ..... };
Hier ist startTransition
eine Funktion. Wenn Sie eine Statusänderung "im Speicher" ausführen möchten, können Sie startTransition
aufrufen und einen Lambda -Ausdruck übergeben, der die Zustandsänderung durchführt.
starttransition (() => { Dispatch ({Typ: load_data_or_ething, Wert: 42}); });
Sie können startTransition
überall anrufen. Sie können es an untergeordnete Komponenten usw. weitergeben. Wenn Sie es nennen, werden alle staatlichen Änderungen im Speicher stattfinden. Wenn eine anstehende Ausübung auftritt, wird isPending
wahr, mit der Sie eine Art Inline -Lastanzeige anzeigen können.
Das war's. Das macht Spannung.
Der Rest dieses Artikels führt einen tatsächlichen Code ein, um diese Funktionen zu nutzen.
Beispiel: Navigation
Um die Navigation mit Spannung zu verbinden, werden Sie sich freuen zu wissen, dass React einen primitiven dafür bietet: React.lazy
. Es ist eine Funktion, die einen Lambda -Ausdruck akzeptiert, der ein Versprechen zurückgibt, das sich in eine React -Komponente auflöst. Das Ergebnis dieses Funktionsaufrufs wird zu Ihrer faulen Ladekomponente. Es klingt kompliziert, aber es sieht so aus:
const EinstellungenComponent = Lazy (() => import ("./ Module/Einstellungen/Einstellungen"));
SettingsComponent
ist jetzt eine React -Komponente, die bei gerenderter (jedoch nicht zuvor) die von uns übergebene Funktion aufruft, in der import()
und das JavaScript -Modul in ./modules/settings/settings
laden.
Der Hauptteil ist: Während import()
im Gange ist die Komponente, die SettingsComponent
rendert, hängt. Es sieht so aus, als hätten wir alle Komponenten in der Hand, also lass sie sie zusammenstellen und eine spannungsbasierte Navigation bauen.
Navigationsassistentenprogramm
Um einen Kontext bereitzustellen, werde ich zunächst kurz vorstellen, wie der Navigationsstatus in dieser Anwendung verwaltet wird, damit der Spannungscode sinnvoller ist.
Ich werde meine Buchliste -Anwendung verwenden. Es ist nur ein persönliches Projekt von mir, das ich hauptsächlich mit modernsten Webtechnologien experimentieren kann. Es wurde allein von mir geschrieben, also erwarten Sie, dass ein Teil davon etwas rau ist (insbesondere das Design).
Die App ist klein und Benutzer können ungefähr acht verschiedene Module ohne tiefere Navigation durchsuchen. Jeder Suchstatus, den das Modul verwenden kann, wird in der Abfragezeichenfolge der URL gespeichert. Vor diesem Hintergrund gibt es Möglichkeiten, den aktuellen Modulnamen und den Suchstatus aus der URL zu extrahieren. Dieser Code verwendet query-string
und history
von NPM, die ein bisschen so aussieht (einige Details wurden zur Einfachheit halber entfernt, wie z. B. Authentifizierung).
Import CreateHistory aus "History/CreateBrowserHistory"; Importieren von QueryString von "Query-String"; Export const history = createHistory (); Exportfunktion getCurrenturlstate () { lass location = history.location; let Parsed = queryString.parse (location.Search); zurückkehren { Pfadname: Ort.PathName, SearchState: Parsen }; } Exportfunktion getCurrentModuleFromUrl () { lass location = history.location; Rückgabeort.PathName.Replace (/\ // g, "") .tolowerCase (); }
Ich habe einen appSettings
-Reduzierer, der das aktuelle Modul- und searchState
-Werte der Anwendung hält und diese Methoden verwendet, um bei Bedarf mit der URL zu synchronisieren.
Spannungsbasierte Navigationskomponenten
Beginnen wir mit einigen Spannungsarbeiten. Lassen Sie uns zunächst faul geladene Komponenten für unser Modul erstellen.
const activateComponent = lazy (() => import ("./ Module/Aktivieren/Aktivieren")); const authenticateComponent = lazy (() => import ("./ Module/authentikat/authentifiziert")); const booksComponent = lazy (() => import ("./ Module/Bücher/Bücher")); const homecomponent = lazy (() => import ("./ modules/home/home")); const Scancomponent = Lazy (() => import ("./ Module/Scan/Scan")); const fatchscomponent = lazy (() => import ("./ Module/Subjekte/Subjekte")); const EinstellungenComponent = Lazy (() => import ("./ Module/Einstellungen/Einstellungen")); const admincomponent = lazy (() => import ("./ modules/admin/admin"));
Jetzt brauchen wir eine Möglichkeit, die richtige Komponente basierend auf dem aktuellen Modul auszuwählen. Wenn wir React Router verwenden, haben wir einige nette<route></route>
Komponenten. Da wir dies manuell tun, funktioniert switch
-Anweisung.
Export const getModulecomponent = moduletoload => { if (moduletoload == null) { null zurückkehren; } Switch (moduletoload.tolowerCase ()) { Fall "aktivieren": ActivateComponent zurückgeben; Fall "authentifiziert": return authenticatecomponent; Fall "Bücher": bookscomponent zurückkehren; Fall "Zuhause": Homecomponent zurückkehren; Fall "Scan": Return Scancomponent; Fall "Themen": Rückgabefächerkomponenten; Fall "Einstellungen": Rückgabeeinstellungen Component; Fall "Administrator": Rückkehr Admincomponent; } Homecomponent zurückkehren; };
Alles zusammensetzen
Nachdem alle langweiligen Setups durchgeführt wurden, sehen wir sehen, wie die gesamte Anwendungswurzel aussieht. Hier gibt es viel Code, aber ich verspreche, dass relativ wenige dieser Zeilen mit Spannung zusammenhängen und ich alle abdecken werde.
const app = () => { const [starttransitionNewmodule, isNewmodulePending] = Usetransition ({{{{ Timeouts: 3000 }); const [startTransitionModulUpdate, moduleupdatepending] = usetransition ({{{{{{{ Timeouts: 3000 }); lass AppStatePacket = useAppstate (); Sei [AppState, _, Dispatch] = AppStatePacket; component = getModulecomponent (AppState.module); useEffect (() => { startTransitionNewmodule (() => { Dispatch ({Typ: url_sync}); }); }, []); useEffect (() => { return history.listen (location => { if (appstate.module! = getCurrentModuleFromUrl ()) { startTransitionNewmodule (() => { Dispatch ({Typ: url_sync}); }); } anders { startTransitionModuleUpdate (() => { Dispatch ({Typ: url_sync}); }); } }); }, [AppState.module]); Zurückkehren ( <appcontext.provider value="{appStatePacket}"> <moduleupdatecontext.provider value="{moduleUpdatePending}"> <div> <mainnavigationbar></mainnavigationbar> {isNewModulePending?<loading></loading> : null} <suspense fallback="{<LongLoading"></suspense> }> <div style="{{" flex: overflowy:> {Komponente?<component updating="{moduleUpdatePending}"></component> : null} </div> </div> </moduleupdatecontext.provider> </appcontext.provider> ); };
Zuerst haben wir zwei verschiedene Anrufe zum useTransition
getätigt. Wir verwenden eine, um das neue Modul und das andere zu leiten, um den Suchstatus des aktuellen Moduls zu aktualisieren. Warum gibt es einen Unterschied? Nun, das Modul möchte möglicherweise eine Inline -Lastanzeige anzeigen, wenn der Suchstatus des Moduls aktualisiert wird. Der Aktualisierungsstatus wird durch die moduleUpdatePending
-Variable gespeichert. Sie werden feststellen, dass ich ihn in den Kontext stecke, damit das aktive Modul abgerufen und bei Bedarf verwendet werden kann:
<div> <mainnavigationbar></mainnavigationbar> {isNewModulePending?<loading></loading> : null} <suspense fallback="{<LongLoading"></suspense> }> <div style="{{" flex: overflowy:> {Komponente?<component updating="{moduleUpdatePending}"></component> : null} </div> </div>
appStatePacket
ist das Ergebnis des oben diskutierten (aber nicht gezeigten) Anwendungszustands. Es enthält verschiedene Anwendungszustandsfragmente, die selten verändert werden (Farbthema, Offline -Status, aktuelles Modul usw.).
lass AppStatePacket = useAppstate ();
Später erhalte ich eine aktive Komponente basierend auf dem aktuellen Modulnamen. Anfangs wird dies null sein.
component = getModulecomponent (AppState.module);
Der erste Aufruf zur useEffect
zeigt uns, dass appSettings
-Reduzierer beim Start mit der URL synchronisiert wird.
useEffect (() => { startTransitionNewmodule (() => { Dispatch ({Typ: url_sync}); }); }, []);
Da dies das anfängliche Modul ist, zu dem die Webanwendung navigiert, wickle ich es in startTransitionNewModule
ein, um anzuzeigen, dass das neue Modul geladen wird. Während es verlockend sein könnte, den ersten Modulnamen des Reduzierers als Ausgangszustand festzulegen, hindert uns dies daran startTransitionNewModule
-Rückruf aufzurufen. Dies bedeutet, dass unsere Spannungsgrenze den Fallback -Inhalt sofort und nicht nach der Zeitüberschreitung macht.
Ein Verlaufsabonnement wird auf den nächsten Anruf eingestellt, um Effectect zu useEffect
. Wie auch immer, wenn sich die URL ändert, werden wir unsere Anwendungseinstellungen mit der URL angeben. Der einzige Unterschied besteht darin, dass startTransition
der gleiche Anruf verpackt ist.
useEffect (() => { return history.listen (location => { if (appstate.module! = getCurrentModuleFromUrl ()) { startTransitionNewmodule (() => { Dispatch ({Typ: url_sync}); }); } anders { startTransitionModuleUpdate (() => { Dispatch ({Typ: url_sync}); }); } }); }, [AppState.module]);
Wenn wir in ein neues Modul stöbern, werden wir startTransitionNewModule
nennen. Wenn wir eine nicht geladene Komponente laden, hängt React.lazy
. Aufgrund der Funktionsweise useTransition
wird der aktuelle Bildschirm drei Sekunden lang weiter angezeigt. Wenn diese Zeit überschritten wird und die Komponente noch nicht fertig ist, hängt unsere Benutzeroberfläche und der Fallback -Inhalt wird gerendert, was angezeigt wird<longloading></longloading>
Komponenten:
{isNewModulePending?<loading></loading> : null} <suspense fallback="{<LongLoading"></suspense> }> <div style="{{" flex: overflowy:> {Komponente?<component updating="{moduleUpdatePending}"></component> : null} </div>
Wenn wir das Modul nicht ändern, werden wir startTransitionModuleUpdate
nennen:
startTransitionModuleUpdate (() => { Dispatch ({Typ: url_sync}); });
Wenn das Update einen Hang verursacht, wird der Hang -Indikator, den wir in den Kontext setzen, abgefeuert. Die aktive Komponente kann dies erkennen und alle gewünschten Inline -Lastanzeigen anzeigen. Wenn die Hängezeit nach wie vor drei Sekunden überschreitet, wird die gleiche Spannungsgrenze ausgelöst ... es sei denn, wir werden später sehen, dass die Spannungsgrenze im unteren Teil des Baumes existiert.
Eine wichtige Sache zu beachten ist, dass diese drei Sekunden Zeitüberschreitungen nicht nur für das Laden von Komponenten, sondern auch für die Bereitschaft angegeben sind. Wenn die Komponente in zwei Sekunden geladen ist und beim Rendern im Speicher (da wir uns im startTransition
-Anruf befinden) aufgehängt ist, warten useTransition
weiterhin auf eine Sekunde, bevor sie erneut hängt.
Während ich diesen Beitrag schrieb, habe ich den langsamen Netzwerkmodus von Chrom verwendet, um das Laden zu erzwingen, um langsamer zu werden, um meine Spannungsgrenzen zu testen. Die Einstellungen befinden sich in der Registerkarte "Netzwerk" von Chrome Development Tools.
Öffnen wir unsere Anwendung zum Einstellungsmodul. Dies wird genannt:
Dispatch ({Typ: url_sync});
Unser appSettings
-Reduzierer synchronisiert mit der URL und setzt das Modul dann auf "Einstellungen". Dies geschieht in startTransitionNewModule
, damit es hängt, wenn die faul geladene Komponente versucht, sie zu rendern. Da wir uns in startTransitionNewModule
befinden, wechselt isNewModulePending
zu True und wird rendern<loading></loading>
Komponenten.
Was passiert also, wenn wir zu einem neuen Ort steigen? Im Grunde genauso wie zuvor, außer diesem Anruf:
Dispatch ({Typ: url_sync});
... wird aus der zweiten Instanz der useEffect
sein. Lassen Sie uns zum Buchmodul suchen und sehen, was passiert. Erstens zeigt der Inline -Spinner wie erwartet:
(Screenshots sollten hier eingefügt werden)
Suche und Update
Lassen Sie uns im Buchmodul bleiben und die URL -Abfrage -Zeichenfolge aktualisieren, um eine neue Suche zu starten. Erinnern Sie sich daran, dass wir dasselbe Modul im zweiten useEffect
-Aufruf erkannt und einen dedizierten useTransition
-Aufruf dafür verwendet haben. Von dort setzen wir den Suspend -Indikator in den Kontext so ein, dass jedes aktive Modul, das für uns abgerufen und verwendet werden kann.
Schauen wir uns einen Code an, der ihn tatsächlich verwendet. Hier gibt es keinen viel spannungsbezogenen Code. Ich erhalte den Wert aus dem Kontext und mache einen Inline -Spinner über meine vorhandenen Ergebnisse. Erinnern Sie sich daran, dass dies geschieht, wenn der useTransition
-Anruf begonnen hat und die Anwendung im Speicher ausgesetzt ist. Während dieser Zeit werden wir weiterhin die vorhandene Benutzeroberfläche angezeigt, jedoch mit diesem Lastanzeige.
const bookResults = ({books, uIview}) => { const isupdating = usecontext (modulEpdateContext); Zurückkehren ( <div> {! books.length? ( <div classname="alert alert-warning" style="{{" margintop: marginright:> Keine Bücher gefunden </div> ): null} {isupdating?<loading></loading> : null} {UIView.isGridView? ( <gridview books="{books}"></gridview> ): uiView.isBasicList? ( <basiclistview books="{books}"></basiclistview> ): uiView.iscoverSlist? ( <coversview books="{books}"></coversview> ): null} </div> ); };
Lassen Sie uns einen Suchbegriff einrichten und sehen, was passiert. Zunächst wird der Inline -Spinner angezeigt.
Wenn useTransition
zeitlich festgelegt ist, erhalten wir den Fallback -Inhalt der Spannungsgrenze. Das Buchmodul definiert seine eigene Spannungsgrenze, um einen feineren Ladeindikator anzugeben, wie unten gezeigt:
(Screenshots sollten hier eingefügt werden)
Dies ist ein wichtiger Punkt. Versuchen Sie, keine Spinner- und Ladenachrichten anzuzeigen, wenn Sie Spanngrenze erstellen. Dies ist sinnvoll für unsere Top -Navigation, da es nichts anderes zu tun gibt. Wenn Sie sich jedoch in einem bestimmten Teil der Anwendung befinden, versuchen Sie, den Fallback -Inhalt viele der gleichen Komponenten wiederzuverwenden und eine Art Lastanzeige anzuzeigen, wo die Daten sind - aber alles andere ist deaktiviert.
So sehen die relevanten Komponenten meines Buchmoduls aus:
const rendermodule = () => { const UIView = UseBookSearchUiview (); const [lastbookResults, setLastbookResults] = usestate ({{{ Gesamtseite: 0,, resultsCount: 0 }); Zurückkehren ( <div classname="standard-module-container margin-bottom-lg"> <suspense fallback="{<Fallback" uiview="{uiView}"></suspense> }> <maincontent setlastbookresults="{setLastBookResults}" uiview="{uiView}"></maincontent> </div> ); }; const fallback = ({uiview, TotalPages, resultingCount}) => { Zurückkehren ( <div> <booksmenubardisabled resultscount="{resultsCount}" totalpages="{totalPages}"></booksmenubardisabled> {UIView.isGridView? ( <gridviewshell></gridviewshell> ): ( <h1> Bücher laden<i classname="fas fa-cog fa-spin"></i> </h1> )} </div> ); };
Kurzanmerkung zur Konsistenz
Bevor wir fortfahren, möchte ich im vorherigen Screenshot auf eine Sache hinweisen. Schauen Sie sich den Inline -Spinner an, der beim Auslegen der Suche angezeigt wird. Schauen Sie sich dann den Bildschirm an, wenn die Suche suspendiert wird, und sehen Sie sich die abgeschlossenen Ergebnisse an:
(Screenshots sollten hier eingefügt werden)
Beachten Sie, ob sich auf der rechten Seite des Suchscheibe ein "C" -Tag befindet, und gibt es eine Option, um es aus der Suchabfrage zu entfernen? Oder beachten Sie, dass sich das Tag nur auf den letzten beiden Screenshots befindet? In dem Moment, in dem die URL aktualisiert wird, wird der Anwendungsstatus, der das Tag kontrolliert, tatsächlich aktualisiert. Der Status wird jedoch zunächst nicht angezeigt. Zunächst hängt das Status -Update im Speicher (weil wir useTransition
verwendet haben) und die vorherige Benutzeroberfläche wird weiterhin angezeigt.
Dann wird der Inhalt gesichert. Der Fallback -Inhalt macht eine deaktivierte Version derselben Suchleiste, in der der aktuelle Suchstatus (basierend auf der Auswahl) angezeigt wird. Wir haben jetzt die vorherige Benutzeroberfläche entfernt (weil sie jetzt ziemlich alt und abgestanden ist) und warten darauf, die in der Menüleiste angezeigte Suche zu deaktivieren.
Dies ist die Art der Konsistenzspannung, die Ihnen kostenlos bietet.
Sie können Zeit damit verbringen, schöne Anwendungsstaaten zu erstellen, und React schlenkt, ob die Dinge fertig sind, ohne dass Sie sich mit dem Versprechen befassen müssen.
Verschachtelte Spannungsgrenzen
Angenommen, unsere obere Navigation dauert eine Weile, bis unsere Buchkomponenten in das Ausmaß geladen werden, in dem unser "noch ladener, sorry" -Pinner von der Spannungsgrenze gerät. Von dort aus wird die Buchkomponente geladen und die neue Spannungsgrenze innerhalb der Buchkomponente wiedergegeben. Aber wenn das Rendering fortgesetzt wird, feuert unsere Buchsuche ab und hängt. was geschieht? Wird die obere Spannungsgrenze weiter angezeigt, bis alles fertig ist, oder wird die unteren Spannungsgrenze im Buch im Buch übernehmen?
Die Antwort ist die letztere. Wenn neue Spannungsgrenzen an einer niedrigeren Position im Baum gerendert werden, ersetzt ihr Fallback -Inhalt den Fallback -Inhalt aller angezeigten Spannungs -Rückeninhalte. Derzeit gibt es eine instabile API, die diese Funktion überschreiben kann. Wenn Sie jedoch einen Fallback -Inhalt gut machen, kann dies das gewünschte Verhalten sein. Sie möchten nicht "noch laden, sorry" weiter angezeigt werden. Sobald die Buchkomponente fertig ist, möchten Sie stattdessen auf jeden Fall eine Shell mit einer gezielteren Wartenachricht anzeigen.
Was ist nun, wenn unser Buchmodul lädt und anfängt zu rendern, wenn startTransition
-Spinner noch zeigt und dann hängt? Mit anderen Worten, annehmen, dass unser Timeout startTransition
drei Sekunden beträgt, die Buchkomponente rendert, die verschachtelte Spannungsgrenze befindet sich nach einer Sekunde im Komponentenbaum und die Suchabfrage wird suspendiert. Werden die verbleibenden zwei Sekunden vergangen oder werden der Fallback unmittelbar vor dieser neuen verschachtelten Spannungsgrenze den Fallback -Inhalt darstellt? Die Antwort kann überraschend sein, dass der neue Spannungs -Fallback -Inhalt standardmäßig sofort angezeigt wird. Dies liegt daran, dass es am besten ist, eine neue gültige Benutzeroberfläche so schnell wie möglich anzuzeigen, damit der Benutzer sehen kann, dass die Dinge geschehen und sich bewegen.
So integrieren Sie Daten
Die Navigation ist gut, aber wie passen das Laden von Daten in alles?
Es mischt sich völlig transparent in es ein. Das Laden von Daten löst einen Hang wie bei React.lazy
Navigation aus und hängt mit den gleichen useTransition
und Spannungsgrenzen an. Deshalb ist Spannung so erstaunlich: Alle asynchronen Abhängigkeiten funktionieren nahtlos in demselben System. Vor der Spannung war die manuelle Verwaltung dieser verschiedenen asynchronen Anfragen, um sicherzustellen, dass die Konsistenz ein Albtraum war, weshalb es genau der Grund hat, warum niemand es getan hat. Webanwendungen sind für kaskadierende Spinner berüchtigt, die zu unvorhersehbaren Zeiten stehen und inkonsistente UIs erzeugen, die nur teilweise abgeschlossen sind.
OK, aber wie verbinden wir die Datenlast tatsächlich damit? Das Laden von Daten in Spannung ist sowohl komplexer als auch einfacher.
Lassen Sie mich erklären.
Wenn Sie auf Daten warten, geben Sie ein Versprechen in die Komponente, die die Daten liest (oder versucht zu lesen). Das Versprechen sollte auf der Grundlage von Datenanfragen konsistent sein. Daher sollten vier doppelte Anfragen für dieselbe "C" -Suchabfrage das gleiche und das gleiche Versprechen werfen. Dies bedeutet eine Art Cache -Ebene, um all dies zu verwalten. Sie werden das wahrscheinlich nicht selbst schreiben. Stattdessen möchten Sie nur die Datenbank, mit der Sie sich selbst aktualisieren, um Suspense zu unterstützen.
Diese Arbeit wurde in meiner Bibliothek mit Micro-Graphql-React-Bibliothek durchgeführt. Sie verwenden den useSuspenseQuery
-Hook anstelle des useQuery
-Hooks, der dieselbe API hat, aber ein einheitliches Versprechen bringt, wenn Sie auf die Daten warten.
Warten Sie, was ist mit Vorspannung? !
Lesen Sie andere Dinge über Spannung, sprechen Sie über Wasserfälle, Rendern, Vorspannung usw. Ist Ihr Gehirn schon verwirrt? Mach dir keine Sorgen. Das bedeutet alles.
Angenommen, Sie verzögern das Laden der Buchkomponente, die dann einige Daten fordert, was zu einer neuen Spannung führt. Die Netzwerkanfragen von Komponenten und Netzwerkanfragen von Daten werden nacheinander nacheinander stattfinden - auf Wasserfall.
Der Schlüsselteil ist jedoch: Wenn Sie mit dem Laden der Komponente beginnen, ist der Anwendungszustand, der eine anfängliche Abfrage ausführt, bereits verfügbar (in diesem Fall die URL). Warum also nicht die Abfrage "beginnen", wenn Sie wissen, dass Sie sie brauchen? Sobald Sie zu /Büchern durchsuchen, können Sie die aktuelle Suchabfrage zu diesem Zeitpunkt sofort starten, damit sie bereits im Laden der Komponente läuft?
Das Micro-Graphql-React-Modul verfügt über eine Vorspannungsmethode, und ich empfehle Ihnen, es zu verwenden. Vorlädungsdaten sind eine gute Leistungsoptimierung, aber sie hat nichts mit Spannung zu tun. Klassische React -Anwendungen können Daten sofort vorladen (und sollten), wenn sie wissen, dass sie sie benötigen. VUE -Anwendungen sollten Daten sofort vorladen, wenn sie wissen, dass sie sie benötigen. Die schlanke Anwendung sollte ... Sie bekommen es.
Die vorinstallierten Daten sind orthogonal zur Spannung, was Sie mit jedem Framework tun können. Dies haben auch etwas, was wir alle hätten tun sollen, obwohl andere es nicht getan haben.
Aber im Ernst, wie hast du vorgeladen?
Es liegt an Ihnen. Zumindest muss die Logik, die aktuelle Suche auszuführen, unbedingt vollständig in ein eigenes unabhängiges Modul unterteilt werden. Sie sollten buchstäblich sicherstellen, dass sich diese Vorspannungsfunktion in einer separaten Datei befindet. Verlassen Sie sich nicht auf Webpack für baumartigen Jitter. Wenn Sie Ihr Paket das nächste Mal überprüft, können Sie vollständige Traurigkeit haben.
Sie haben eine preload()
-Methode in einem eigenen Paket, also nennen Sie sie. Rufen Sie es an, wenn Sie wissen, dass Sie zum Modul navigieren möchten. Ich gehe davon aus, dass React Router über einige APIs verfügt, die bei Änderungen der Navigation Code ausführen können. Für den oben genannten nativen Routing -Code habe ich die Methode im vorherigen Routenwechsel aufgerufen. Ich habe es für die Kürze weggelassen, aber der Bucheintrag sieht tatsächlich so aus:
Switch (moduletoload.tolowerCase ()) { Fall "aktivieren": ActivateComponent zurückgeben; Fall "authentifiziert": return authenticatecomponent; Fall "Bücher": // Vorspannung! ! ! booksPreload (); bookscomponent zurückkehren;
Das war's. Hier ist eine Live -Demonstration, die Sie versuchen können:
(Der Link sollte hier eingefügt werden)
Um den Spannungs -Zeitlimitwert zu ändern (Standardwert beträgt 3000 Millisekunden), navigieren Sie zu Einstellungen und sehen Sie sich die anderen Registerkarten an. Achten Sie nach der Änderung unbedingt die Seite.
Zusammenfassen
Ich war so aufgeregt über alles im Webentwicklungsökosystem wie mit Spannung. Es ist ein äußerst ehrgeiziges System, um eines der schwierigsten Probleme in der Webentwicklung zu verwalten: Asynchronität.
Das obige ist der detaillierte Inhalt vonReagieren Sie in der Praxis Spannung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Es ist aus! Herzlichen Glückwunsch an das Vue -Team, dass es eine massive Anstrengung war und lange kommt. Alle neuen Dokumente auch.

Mit dem jüngsten Aufstieg von Bitcoins Preis über 20.000 USD und kürzlich von 30.000, dachte ich, es lohnt

Ich ließ jemanden mit dieser sehr legitimen Frage einschreiben. Lea hat gerade darüber gebloggt, wie Sie gültige CSS -Eigenschaften selbst aus dem Browser erhalten können. Das ist so.

Neulich habe ich dieses besonders schöne Stück von der Website von Corey Ginnivan entdeckt, auf der eine Sammlung von Karten aufeinander stapelt.

Ich sage "Website" passt besser als "Mobile App", aber ich mag dieses Rahmen von Max Lynch:

Wenn wir dem Benutzer direkt im WordPress -Editor Dokumentation anzeigen müssen, wie können Sie dies am besten tun?

Es gibt eine Reihe dieser Desktop -Apps, in denen das Ziel Ihre Website gleichzeitig in verschiedenen Dimensionen angezeigt wird. So können Sie zum Beispiel schreiben

Fragen zu lila Schrägstrichen in Flex -Layouts Bei der Verwendung von Flex -Layouts können Sie auf einige verwirrende Phänomene stoßen, wie beispielsweise in den Entwicklerwerkzeugen (D ...
