Join the discussion
Comments
Loading comments...
Cookie preferences
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Join the discussion
Loading comments...
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Prioritätsbasierte Updates — dringendes vs. nicht-dringendes Rendering mit startTransition.
useTransition ist ein React 18-Hook, mit dem Sie Zustandsupdates als 'nicht-dringende Übergänge' markieren können. Dringende Updates (Tippen, Klicken) werden sofort verarbeitet und nie unterbrochen. Übergangs-Updates haben niedrigere Priorität — wenn ein dringendes Update eintrifft, während ein Übergang in Bearbeitung ist, unterbricht React den Übergang, erledigt die dringende Arbeit und startet dann den Übergang neu. Dies hält die Benutzeroberfläche reaktionsfähig, auch während schwerer Re-Renderings.
Der React-Scheduler weist jedem Update eine Prioritätslane zu: SyncLane (dringend, nicht batchbar), InputContinuousLane (Ziehen/Scrollen), DefaultLane (normales setState) und TransitionLane (useTransition / startTransition). Höherprioritäre Lanes verdrängen immer niederprioritäre.
Einen setState-Aufruf in startTransition(callback) einzuwickeln, teilt React mit: 'Dieses Update ist ein Übergang — es kann unterbrochen werden'. React plant es in einer TransitionLane ein und hält die aktuelle Benutzeroberfläche sichtbar, bis der Übergang abgeschlossen ist.
Wenn der Benutzer ein weiteres Zeichen tippt, während eine 5000-Elemente-Liste als Übergang neu rendert, pausiert React das Übergangs-Rendering mitten im Baum, verarbeitet sofort das Tippen (dringend), aktualisiert die Eingabe und startet dann den Übergang mit dem neuen Eingabewert von vorne.
useTransition gibt [isPending, startTransition] zurück. isPending ist true, während React den Übergang verarbeitet. Verwenden Sie es, um eine subtile Ladeanzeige zu zeigen, ohne die Benutzeroberfläche zu blockieren.
Eine Alternative zu startTransition: useDeferredValue(wert) gibt eine verzögerte Kopie des Werts zurück, die während Übergängen hinterherhinkt. Die Benutzeroberfläche rendert zuerst mit dem alten verzögerten Wert (schnell), dann rendert sie mit dem neuen Wert erneut, wenn React Zeit hat.
Eine niederprioritäre Scheduler-Lane für Übergangs-Updates. Kann von jeder höherprioritären Arbeit (Benutzereingabe, synchrone Updates) verdrängt werden.
Markiert die setState-Aufrufe in seinem Callback als nicht-dringend. Als eigenständiger Import oder vom useTransition-Hook verfügbar.
Boolean von useTransition. True, während React das Übergangs-Update noch verarbeitet. Zum Anzeigen eines Spinners ohne Blockierung der Eingabe verwenden.
Gibt eine verzögerte Kopie eines Werts zurück. Rendert zuerst mit dem veralteten Wert (sofort), rendert mit dem frischen Wert erneut, wenn inaktiv. Nützlich zum Filtern großer Listen.
Wenn ein dringendes Update mitten in einem Übergang eintrifft, verwirft React das laufende Übergangs-Rendering und startet es nach Erledigung der dringenden Arbeit frisch neu.
1import { useState, useTransition } from 'react';23function SearchPage() {4 const [query, setQuery] = useState('');5 const [results, setResults] = useState(allItems);6 const [isPending, startTransition] = useTransition();78 function handleChange(e) {9 // Urgent: update the input immediately (never interrupted)10 setQuery(e.target.value);1112 // Non-urgent: filter 10,000 items as a transition13 startTransition(() => {14 setResults(allItems.filter(item =>15 item.name.includes(e.target.value)16 ));17 });18 }1920 return (21 <>22 <input value={query} onChange={handleChange} />23 {isPending && <Spinner />} {/* subtle loading indicator */}24 <ResultsList items={results} />25 </>26 );27}
Vor Übergängen renderte React alle Zustandsupdates mit derselben Priorität — ein schweres Listen-Re-Rendering konnte die Eingabe für Hunderte von Millisekunden einfrieren. Übergänge ermöglichen es, React explizit mitzuteilen: 'Der Benutzer braucht das Eingabefeld sofort, aber die Ergebnisliste kann einen Moment warten'. Dies ist der Unterschied zwischen einer trägen App und einer flüssigen, wenn teure Renderings verarbeitet werden.
A dashboard has tabs: Overview, Analytics, Reports. Clicking 'Analytics' loads heavy chart components. Without transitions, the current tab disappears immediately and the user sees a loading blank until the new tab renders.
The tab switch calls `setActiveTab('analytics')`, which immediately unmounts the Overview tab and starts rendering Analytics. The heavy chart render blocks the main thread for 300ms. During this time, the user sees a blank panel — the old tab is gone, the new tab isn't ready.
Wrap the tab switch in `startTransition(() => setActiveTab('analytics'))`. React keeps showing the Overview tab (marked with `isPending` for a subtle opacity/spinner indicator) while rendering Analytics in the background. When ready, it swaps them in a single frame — no blank state.
Takeaway: useTransition is perfect for tab switching, accordion expansions, and any UI where you want the old content to stay visible while new content prepares. The `isPending` boolean lets you show a subtle loading indicator without destroying the current view.
A search results component receives `query` as a prop and does heavy filtering inline. You want to defer the results rendering but can't wrap the parent's setState in startTransition because you don't control the parent.
The parent component calls `setQuery(e.target.value)` directly. You can't add startTransition because you don't own the parent component (maybe it's from a library). Your heavy ResultsList re-renders on every keystroke because `query` prop changes immediately.
Use `useDeferredValue(query)` in ResultsList: `const deferredQuery = useDeferredValue(query)`. Filter using `deferredQuery` instead of `query`. React returns the old value during heavy renders, showing stale-but-fast results while computing the new filter in the background. Compare `query !== deferredQuery` to show a loading indicator.
Takeaway: useDeferredValue is the consumer-side equivalent of useTransition. Use useTransition when you control the state update (can wrap setState). Use useDeferredValue when you want to defer derived rendering from a prop you don't control.