Event bubbling and capturing are the two directions an event travels through the React tree. In bubbling, the handler on the innermost element runs first and the event then moves up to its parents. In capturing, the event travels from the top down before it reaches the target.
Bubbling runs bottom up
Most React events bubble by default. When you click a button inside a div, the button's handler runs first, then the div's handler, then any handler higher up the tree.
function Toolbar() {
return (
<div onClick={() => alert("Toolbar clicked")}>
<button onClick={() => alert("Button clicked")}>Save</button>
</div>
);
}Click Save and two alerts appear: the button first, then the toolbar. A click on the button is also a click on the div that contains it, so the event bubbles upward after the button's own handler runs.
Not every event bubbles. The scroll event stays on the element it is attached to, which is why a scroll handler on a parent does not fire for a child's scroll.
Capturing runs top down
Capturing reverses the order. Add Capture to the end of a prop name, so onClick becomes onClickCapture, and the handler runs before the target's own handler.
<div onClickCapture={() => alert("Toolbar first")}>
<button onClick={() => alert("Button clicked")}>Save</button>
</div>Now the toolbar fires first, then the button. Every event actually passes through three phases:
- Capture handlers run from the root down to the target.
- The target's own handlers run.
- Bubble handlers run from the target back up to the root.
Capture handlers are rare in application code. They are mostly useful for analytics or routers that must see every event before anything else can stop it.
target and currentTarget
Two event properties tell you where the event is. e.target is the element where the event started, and it stays the same as the event bubbles. e.currentTarget is the element whose handler is currently running, so it changes as the event moves up.
In a list with one click handler, e.target is the row the user clicked while e.currentTarget is the list itself. Keeping the two apart is what makes a single delegated handler work.
Why bubbling is useful
Bubbling makes event delegation possible. One handler on a list can catch clicks from any row instead of wiring every row separately. The handler reads e.target to learn which row was clicked, which keeps a long list cheap to maintain.
What to learn next
When a parent handler fires but should not, stopping propagation keeps the event from moving up. The object those handlers receive is explained in React synthetic events.
Rune AI
Key Insights
- Bubbling runs child handlers before parent handlers.
- Capturing runs parent handlers first on the way down.
- Add Capture to a prop name for the capture phase.
- target never changes while the event bubbles.
- Bubbling enables event delegation on lists.
Frequently Asked Questions
Which runs first, the child or the parent handler?
How do I use the capture phase in React?
What is the difference between target and currentTarget?
Conclusion
Bubbling runs handlers from the target upward, and capturing runs them from the top down. React uses bubbling by default and adds the Capture suffix for the reverse order.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.