Lesson 11 of 29
Web-Aligned Event Dispatching
Native event dispatch is being reshaped to match the DOM: capture and bubble phases, a composed event path, pointer events, and stopPropagation with the semantics you already know.
React Native's touch and gesture handling has historically been its own system — the "responder" model — with its own rules about who captures a touch, how it can be stolen, and what cancellation looks like. That model worked, but it never quite matched the DOM events most of its users already knew. The platform has been quietly closing that gap for a few releases now, and in current versions the native event dispatcher is designed to behave the same way a browser's does. This lesson is about what that means in practice.
The old shape, in one paragraph
Classic React Native dispatched touches through a responder negotiation: components could claim to be the responder for a given touch, pass it to parents or children, and lose it mid-gesture if another component "stole" it. It was powerful, but the rules were idiosyncratic and didn't map onto any model outside React Native itself. If you learned DOM events first (and most people do), you had to unlearn them to debug a nested scroll-plus-swipe-plus-tap bug.
The shape events take now
The direction set by the platform is that events flow through the same two-phase model the DOM uses:
- Step 1
Capture phase
Listeners along the path from the root to the event target fire first, top-down. An ancestor can observe, log, or stopPropagation before the target ever sees the event.
- Step 2
Target
The deepest component the event is aimed at receives it. In most apps, this is the handler you wrote on the component the user actually touched.
- Step 3
Bubble phase
Listeners fire again from the target back up to the root. A parent Pressable's onPress runs after the child's — unless something along the way stops propagation.
The event object also gains the shape you'd recognise from the web:
event.target, event.currentTarget, event.composedPath() (returning
the list of components the event is travelling through), and the
cancellation methods stopPropagation() and preventDefault() with
their familiar semantics. Pointer-style events — pointerdown,
pointermove, pointerup — are the first-class way the platform
expresses "a thing touched the screen, moved, lifted," unifying touch,
mouse, and pen input under one API, exactly like PointerEvent on the
web.
The two concrete reasons this matters
The first is shared code. A gesture-handling library, a form library, an accessibility tool — anything that cares about event dispatch — can now share one implementation across web and native. React Native for Web projects benefit obviously; cross-platform component libraries benefit even if you don't ship to web yourself, because the libraries you depend on have fewer forks to maintain, which translates to fewer platform- specific bugs for you to work around.
The second is a mature spec to lean on. The DOM event model has been
specified, documented, and debugged by the web community for two
decades. When an edge case comes up — "what happens if I call
preventDefault inside a passive listener?", "does focus move before or
after click?", "how does pointer capture interact with removal from
the DOM?" — there's a published answer rather than an empirical "try it
and see." React Native inheriting that spec is cheaper than maintaining
its own version of the same answers, and it means fewer undocumented
quirks you have to discover by hitting them in production.
What this changes in your own component code
For the common case — one Pressable, one onPress, done — nothing
changes. The simple handler you've always written still works the same
way.
Where it changes is anywhere you previously needed the responder system to do something intricate:
- Nested interactive components become easier. A
Pressableinside a scrollable parent inside a modal follows the capture / bubble rules you already know. You stop writing responder-negotiation code and start writing the samestopPropagation()you'd write on the web. - Pointer-based gestures have a standard API. Custom drag, hover
(on platforms that support it), and pen interactions don't need a
separate "is this a mouse, a touch, or a stylus?" branch — the
pointer event tells you, through the same
pointerTypefield a browser would use. - Accessibility and focus events become more consistent. Focus, blur, and key events behave as the DOM specifies, which matches what assistive-technology APIs on both platforms expect.
When the two models meet
The responder system hasn't vanished overnight — existing libraries
still depend on it, and the platform has been careful to keep them
working. In practice, that means code written against the old touch
responder API continues to function, and new code gets the web-aligned
model. The migration is gradual and the failure mode of mixing the two
in one app is "an occasional edge case where the two systems disagree"
rather than "nothing works." As with the New Architecture itself, the
useful skill is knowing the new model exists and reaching for it when
writing new gesture-heavy code, not rewriting every existing
PanResponder in the app the day a new release lands.
What to remember
- Native event dispatching is being aligned with the W3C UI Events model: capture → target → bubble,
composedPath,stopPropagation/preventDefaultwith DOM semantics, and first-class pointer events. - The same mental model you use for DOM events now applies to native events. Nested interactive components become predictable without responder-negotiation code.
- Two concrete payoffs: cross-platform libraries can share one event implementation, and the DOM spec answers edge cases that previously required empirical discovery.
- Day-to-day component code (one
Pressable, oneonPress) is unchanged. The savings show up in gesture-heavy and cross-platform work. - The legacy touch-responder system hasn't disappeared — existing code keeps working. The migration is gradual, and the new model is the one to reach for in new code.
Check yourself
4 questions · pass 3/4 to unlock TextInput and Forms
1.What does the phrase 'web-aligned event dispatching' actually mean in React Native's context?
2.Under the aligned model, what order do listeners along the path from the root to the target actually fire in?
3.A parent
Pressablewraps a childPressable. The user presses the child. How doesstopPropagation()in the child's handler affect the parent?4.Why does aligning native event dispatch with the web model matter beyond 'it feels familiar'?
4 left to answer
Discussion
Sign in to postNo comments yet. Be the first to say something.