Entdecke, wie Fiber den Baum abgleicht, Updates bündelt und die Render-Arbeit unterbrechbar macht.
Diese Lektion in Kodokon öffnenSeit React 16 heißt die interne Engine Fiber: Jedes Element in deinem Baum wird durch einen Fiber-Knoten dargestellt, eine Arbeitseinheit. React verwaltet in Wirklichkeit zwei Bäume (eine Double-Buffering-Technik): den current-Baum, der widerspiegelt, was auf dem Bildschirm ist, und den workInProgress-Baum, der während des Renderings aufgebaut wird. Die Arbeit läuft in zwei getrennten Phasen ab: die Render-Phase (Aufruf deiner Komponenten, Berechnung der Unterschiede), die unterbrechbar und wiederholbar ist, dann die Commit-Phase (Anwenden der Mutationen auf das DOM, Ausführen der Effekte), die immer synchron und unterbrechungsfrei ist. Reconciliation stützt sich auf zwei Heuristiken, die den Vergleich auf lineare Kosten senken: Ändert sich der Typ eines Elements an einer bestimmten Position, zerstört React den gesamten Teilbaum und baut ihn neu auf, samt State; bei Listen ermöglicht die key-Prop React, Elemente zwischen zwei Renders einander zuzuordnen.
function List({ items }) {
return (
<ul>
{items.map((item) => (
<li key={item.id}>
<input defaultValue={item.label} />
</li>
))}
</ul>
);
}
// With key={index}, deleting the first item
// would shift the content of the remaining inputs.Der zweite grundlegende Mechanismus: Batching. Wenn mehrere State-Updates im selben Kontext ausgelöst werden, fasst React sie zu einem einzigen Render zusammen. Vor React 18 funktionierte diese Bündelung nur innerhalb von React-Event-Handlern; seit createRoot läuft sie überall automatisch: Timer, Promises, native Listener. Deshalb liefert das Lesen des States direkt nach einem setState auch den alten Wert: Das Update ist eingeplant, nicht angewendet.
function handleTick() {
setCount((c) => c + 1);
setFlag((f) => !f);
// React 18: a single render, even here.
}
setTimeout(handleTick, 100);
// Before React 18, this timer would trigger
// two successive renders.Concurrent Rendering treibt die Logik weiter: Die Render-Phase kann unterbrochen, fortgesetzt oder sogar verworfen und neu gestartet werden, wenn ein dringenderes Update eintrifft. React ordnet Updates nach Priorität (den Lanes): Ein Tastendruck ist dringend, ein mit startTransition markierter Listenfilter nicht. Die unmittelbare Folge: Deine Komponentenfunktionen müssen rein sein, denn React ruft sie unter Umständen mehrmals auf, ohne das Ergebnis je zu committen. Ein weiterer Grenzfall: Ein externer Store (Redux, Zustand, ein selbstgebautes Singleton), der während eines unterbrechbaren Renders gelesen wird, kann sich mitten im Render ändern und eine inkonsistente Oberfläche erzeugen, bekannt als Tearing. Die useSyncExternalStore-API löst dieses Problem, indem sie bei einer Änderung des Stores einen synchronen Render erzwingt.
import { useSyncExternalStore } from 'react';
function useWindowWidth() {
return useSyncExternalStore(
(notify) => {
window.addEventListener('resize', notify);
return () =>
window.removeEventListener('resize', notify);
},
() => window.innerWidth
);
}<div>-Element an derselben Position zu einem <span> wird?createRoot zwei setState-Aufrufe innerhalb eines setTimeout aus?