Mobile Development 9 min read

Deep Dive into React Native’s Native Event‑Handling Path: From RCTRootView to the JavaScript Bridge

This article thoroughly analyzes React Native’s native event‑handling pipeline, explaining how RCTRootView creates RCTRootContentView and RCTTouchHandler, detailing the touchesBegan/touchesMoved/touchesEnded implementations, and tracing the flow through _updateAndDispatchTouches, RCTEventDispatcher, and the bridge that finally invokes JavaScript callbacks.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Deep Dive into React Native’s Native Event‑Handling Path: From RCTRootView to the JavaScript Bridge

React Native’s event system starts with RCTRootView , which creates a RCTRootContentView that registers itself as the true root view via _bridge.uiManager registerRootView . Inside the content view a RCTTouchHandler (a subclass of UIGestureRecognizer ) is attached to intercept all touch events.

When a touch begins, touchesBegan:withEvent: is called on RCTTouchHandler . The method records new touches, updates the internal touch state, and forwards the event to _updateAndDispatchTouches:eventName: with the name "touchStart" . Similar logic exists for touchesMoved , touchesEnded , and touchesCancelled , each invoking _updateAndDispatchTouches with the appropriate event name.

The core of the native side is the _updateAndDispatchTouches:eventName: method. It builds an array of changed touch indexes, creates a copy of the current touch data, determines whether the event can be coalesced, and finally constructs an RCTTouchEvent object:

- (void)_updateAndDispatchTouches:(NSSet
*)touches eventName:(NSString *)eventName { … }

The event is then handed to RCTEventDispatcher via sendEvent: . The dispatcher notifies observers, checks for coalescing, queues the event ID, and schedules a dispatch on the JavaScript thread.

- (void)sendEvent:(id
)event { … }

During dispatch, flushEventsQueue iterates over the queued event IDs, retrieves each event, and calls dispatchEvent: . This method logs the event name and enqueues a JavaScript call through the bridge:

- (void)dispatchEvent:(id
)event { NSLog(@"xiaowei.li:%@", event.eventName); [_bridge enqueueJSCall:[event class] moduleDotMethod args:[event arguments]]; }

The bridge’s enqueueJSCall:method:args:completion: validates the bridge, splits the moduleDotMethod string, and ultimately invokes the JavaScript function via the native instance:

- (void)enqueueJSCall:(NSString *)module method:(NSString *)method args:(NSArray *)args completion:(dispatch_block_t)completion { if (!self.valid) return; [_reactInstance callJSFunction:[module UTF8String] [method UTF8String] convertIdToFollyDynamic(args ?: @[])]; }

Thus, the touch event travels from the iOS gesture recognizer, through a series of native Objective‑C classes, into a serialized event object, and finally reaches JavaScript where the React Native runtime processes it. The article also lists related classes and protocols such as RCTRootView , RCTTouchHandler , RCTEventDispatcher , RCTBridge , RCTBatchedBridge , and RCTCxxBridge .

iOSReactNativeBridgeEventHandlingNativeModulesRCTTouchHandler
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.