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.
Reacts Ereignisdelegation, synthetisches Ereignis-Wrapping und Bubbling von der Wurzel.
React fügt Event-Listener nicht direkt an DOM-Elemente an. Stattdessen verwendet es Event-Delegation — ein einziger Listener wird am Root-Container angebracht (dem div, wo ReactDOM.createRoot() aufgerufen wurde). Wenn ein natives Ereignis bis zur Wurzel hochblubbert, fängt React es ab, hüllt es in ein SyntheticEvent-Objekt ein und löst es durch den React-Komponentenbaum aus.
Wenn Sie onClick='{'handleClick'}' in JSX schreiben, ruft React addEventListener nicht auf diesem DOM-Knoten auf. Stattdessen registriert es einen einzigen Listener am Root-Container für 'click'-Ereignisse — dies geschieht einmal für die gesamte App, nicht einmal pro Komponente.
Wenn Sie auf eine Schaltfläche klicken, feuert der Browser ein natives click-Ereignis auf der Schaltfläche, das durch den echten DOM-Baum zur Dokument-Wurzel hochblubbert — wo Reacts Listener wartet.
React hüllt das native Ereignis in ein SyntheticEvent ein — ein browserübergreifend normalisiertes Ereignisobjekt, das unabhängig vom Browser dieselbe API bereitstellt. In älteren React-Versionen wurden SyntheticEvents für die Leistung gepoolt und wiederverwendet.
React durchläuft den Fiber-Baum vom Zielelement bis zur Wurzel und ruft alle onClick- (oder andere Ereignis-) Handler auf, die es an jedem Fiber findet. Dies simuliert Browser-Bubbling, aber in Reacts virtuellem Baum.
Genau wie native Ereignisse unterstützt React Capture-Phase-Handler über onClickCapture. Diese werden von oben nach unten ausgeführt (Wurzel → Ziel), bevor Bubble-Phase-Handler von unten nach oben ausgeführt werden (Ziel → Wurzel).
Ein Listener an der Wurzel verarbeitet alle Ereignisse dieses Typs. Viel effizienter als das Anbringen von Listenern an jedem interaktiven Element.
Reacts browserübergreifender Ereignis-Wrapper. Normalisiert Inkonsistenzen zwischen Browsern. Bietet die nativeEvent-Eigenschaft für den Rohzugang.
Ereignis wird vom Zielelement aufwärts durch Vorfahren-Elemente weitergegeben. Standardphase für die meisten React-Event-Handler.
Ereignis wird von der Wurzel abwärts zum Ziel weitergegeben, bevor es hochblubbert. onClickCapture für die Capture-Phase verwenden.
Stoppt die Weitergabe des Ereignisses durch Reacts simulierten Baum. Stoppt das native Ereignis NICHT, es sei denn, es wird auf e.nativeEvent aufgerufen.
1// React attaches ONE listener to the root — not to each button:2// root.addEventListener('click', reactHandler)34function App() {5 return (6 <div onClick={() => console.log('div — bubble')}>7 <button8 onClick={(e) => {9 console.log('button — bubble');10 // e.stopPropagation() would stop div from firing11 }}12 onClickCapture={() => console.log('button — capture')}13 >14 Click me15 </button>16 </div>17 );18}1920// Click order:21// 1. button — capture (capture phase, top-down)22// 2. button — bubble (bubble phase, bottom-up)23// 3. div — bubble (bubble phase, continues up)
Event-Delegation macht React hocheffizient — egal wie viele Schaltflächen in Ihrer App vorhanden sind, es gibt nur einen nativen Event-Listener pro Ereignistyp. Es bedeutet auch, dass React Ereignisse auch für dynamisch hinzugefügte Komponenten abfangen und verarbeiten kann, und es ermöglicht Reacts synthetischem Ereignissystem, konsistent in allen Browsern zu funktionieren.
You add a native `document.addEventListener('click', closeMenu)` to close a dropdown on outside click. Inside the dropdown, you call `e.stopPropagation()` on the React onClick — but the menu still closes.
React's stopPropagation stops propagation within React's synthetic event system (which uses delegation at the root). But the native listener on `document` has already received the event since React 17+ attaches to `root`, not `document`. The native handler fires before React can stop it.
Use `e.nativeEvent.stopImmediatePropagation()` to stop the native event from reaching other native listeners, or better yet, replace the native listener with a React `onClickCapture` on a wrapper div. Keep event handling within React's system to avoid mixed delegation conflicts.
Takeaway: React's event system runs inside a single delegated listener at the root container. Mixing React events with native `addEventListener` creates ordering conflicts. Prefer keeping all event logic within React's system for predictable behavior.
Legacy code from React 16 calls `e.persist()` in event handlers to use the event in async callbacks. After upgrading to React 18, you see that removing `e.persist()` works fine — but no one on the team understands why.
React 16 used event pooling — SyntheticEvent objects were reused after the handler returned, setting all properties to null. Accessing `e.target` in a setTimeout would return null unless you called `e.persist()`. Teams kept adding persist() defensively everywhere.
React 17+ removed event pooling entirely. SyntheticEvent objects are no longer reused — they persist naturally. All `e.persist()` calls can be safely removed. Understanding this change helps teams clean up legacy code and stop defensive coding patterns that are no longer needed.
Takeaway: React's event system evolves across versions. Event pooling removal (React 17), root-level delegation (React 17), and automatic batching in event handlers (React 18) are all changes that affect how you write event handling code. Stay current with the release notes.