React-UI-Aktualisierungsprozess: Von der Auslösung bis zum Commit
React aktualisiert die Benutzeroberfläche nach einem strengen Ablauf: Auslöser → Rendern → Commit. Während der Rendephase berechnet React den neuen virtuellen DOM-Baum, ohne den echten DOM zu berühren. Die Commit-Phase wendet die Änderungen dann synchron an. Diese Trennung ermöglicht Leistungsverbesserungen – besonders im konkurrierenden Modus, bei dem das Rendern je nach Priorität unterbrochen werden kann.
Rendephase: Rekonstruktion und der Fiber-Baum
Die Rendephase erstellt einen Arbeitsbaum basierend auf der aktuellen Fiber-Struktur. Ein Fiber ist eine verkettete Liste von Knoten, die die Komponentenhierarchie darstellen. Jeder Knoten verweist über die alternate-Eigenschaft auf seine vorherige Version, um den Unterschied (Diff) zu ermitteln.
Die Rekonstruktion vergleicht neue React-Elemente (aus JSX) mit den alten. Stabile key-Werte sorgen für präzise Übereinstimmung und minimieren unnötige Aktualisierungen.
Diese Phase gliedert sich in zwei Stufen: beginWork (top-down) und completeWork (bottom-up):
- beginWork: Prüft, ob ein Rendering erforderlich ist (Bailout, falls nicht), ruft die Render-Funktion auf, setzt Flags (Placement, Update, Deletion) und rekursiviert in die Kinder.
- completeWork: Finalisiert einen Knoten nach der Verarbeitung seiner Kinder und aggregiert Flag-Informationen aus dem Unterbaum, um den Commit zu optimieren.
Unterbaum-Flags leiten Änderungsinformationen nach oben und lassen saubere Zweige während des Commits überspringen.
| Flag | Beschreibung |
|------|-------------|
| Placement | Einfügen eines DOM-Knotens |
| Update | Aktualisieren von Attributen oder Text |
| Deletion | Entfernen eines Elements |
| Ref | Behandlung von Referenzen |
| Layout | Planung von useLayoutEffect |
| Passive | Planung von useEffect |
Flags werden während der Rendephase gesetzt und während des Commits ausgeführt.
Commit-Phase: DOM-Manipulation
Die Commit-Phase ist synchron und atomar und unterteilt sich in drei Teilphasen:
- beforeMutation: Ruft
getSnapshotBeforeUpdate(für Klassenkomponenten) auf und bereinigt alte Referenzen. - mutation: Wendet die Flags an – fügt, aktualisiert oder entfernt DOM-Knoten.
- layout: Führt
componentDidMount/Update,useLayoutEffectsynchron aus, aktualisiert Referenzen und plantuseEffect.
Nach der Layout-Phase übernimmt der Browser: Styles neu berechnen → Layout/Reflow → Zeichnen → Compositing. React greift in diese Schritte nicht ein.
Browser-Pipeline nach Commit
useEffect wird asynchron ausgeführt, nachdem das Zeichnen abgeschlossen ist – aber bei diskreten Ereignissen (Klick, Tastendruck, Eingabe) kann es vor dem Zeichnen laufen, um die Reaktionsfähigkeit zu gewährleisten.
Diskrete Ereignisse:
- click, keydown, input, submit
Kontinuierliche Ereignisse (scroll, mousemove) laufen immer nach dem Zeichnen.
Konkurrierender Modus: Unterbrechbares Rendern
Im konkurrierenden Modus wird das Rendern in priorisierte Arbeitseinheiten aufgeteilt. Hochpriorisierte Updates (wie Tippen) können niedrigpriorisierte (frühere Rendervorgänge) unterbrechen und den Arbeitsbaum verworfen werden.
Der Commit bleibt unverändert: synchron und pro Update nur einmal. Dies gewährleistet die Konsistenz des DOM.
Das Rendern kann mehrfach neu starten, ohne dass ein Commit erfolgt, wenn Updates abgebrochen werden.
Wichtige Erkenntnisse
- Das Rendern berechnet Änderungen im Speicher; DOM-Manipulationen finden nur im Commit statt, wenn Flags vorhanden sind.
beginWork/completeWorkoptimieren die Durchquerung durch Bailout und Unterbaum-Flags.useLayoutEffectläuft synchron nach der Mutation;useEffectläuft asynchron nach dem Zeichnen.- Der konkurrierende Modus erlaubt das Unterbrechen des Renderns, aber der Commit bleibt unteilbar.
- Stabile Keys sind entscheidend für eine effiziente Rekonstruktion.
— Editorial Team
Noch keine Kommentare.