How React Native Bridges Native and JavaScript: Deep Dive into Cross‑Platform Communication
This article explains the architecture and workflow of React Native's cross‑platform communication, detailing the JSBridge mechanism, the roles of platform, bridge, and JS layers, and how native modules interact with JavaScript through C++ and JNI, with a concrete setTimeout example.
Cross‑Platform Communication
In mobile development a single codebase that runs on Android and iOS is a cross‑platform solution. WebView and React Native (RN) are common, but they cannot directly invoke native capabilities. The mechanism that lets an HTML5 (H5) or RN page call native code is called cross‑platform communication or JSBridge.
JSBridge parameters
A JSBridge call carries four default parameters:
ModuleId: module ID
MethodId: method ID
params: arguments
CallbackId: JS callback nameModuleId and MethodId locate the native method, params supplies arguments, and CallbackId returns the result to JavaScript.
RN architecture
React Native consists of three layers:
Platform layer (Android or iOS) – implements native components and capabilities.
Bridge layer (C++) – parses JavaScript and mediates calls between Java/Objective‑C and JavaScript.
JS layer – contains the business logic of the cross‑platform page.
Bridge layer (C++)
RN uses JSCore as its JavaScript engine. The engine’s external interface is written in C/C++, so the platform code accesses JavaScript through C++ APIs. This design enables the same bridge code to run on both Android and iOS.
JSCore core APIs
JSContextGetGlobalObject // get the global object
JSObjectSetProperty / JSObjectGetProperty // set and get object properties
JSEvaluateScript // execute a script
JSObjectCallAsFunction // call a JavaScript functionNative and JavaScript modules
Native modules (Java on Android) reside under java/com/facebook/react/modules/ (e.g., the Timing module). JavaScript modules live in /Libraries/ReactNative/ (e.g., AppRegistry) and expose APIs such as callFunctionReturnFlushedQueue.
Both sides maintain mappings: NativeModules (moduleID → methodID) for native‑to‑JS calls and JSModuleRegistry for JS‑to‑native calls. All communication passes through the C++ bridge.
C++ ↔ JS communication
JS injects a global variable __fbBatchedBridge with four entry APIs:
callFunctionReturnFlushedQueue
invokeCallbackAndReturnFlushedQueue
flushedQueue
callFunctionReturnResultAndFlushedQueueIt also defines __fbGenNativeModule to generate the NativeModules mapping, e.g.:
{
"Timing": {
"moduleID": "1001",
"method": {
"createTimer": { "methodID": "10001" }
}
}
}C++ uses JSObjectSetProperty to expose native APIs such as nativeFlushQueueImmediate, nativeCallSyncHook, and nativeRequire.
Java ↔ C++ via JNI
Java communicates with C++ through JNI. The bridge exposes methods like:
initializeBridge
jniLoadScriptFromFile
jniCallJSFunction
jniCallJSCallback
setGlobalVariable
getJavaScriptContextThese methods allow Java to load scripts, invoke JS functions, and handle callbacks, completing the call chain.
setTimeout call flow example
The setTimeout implementation illustrates a full round‑trip:
During RN initialization the Timing class is registered as a native module.
The ModuleRegistry is built and passed to C++ via initializeBridge, which registers it in the JS environment.
JavaScript’s JSTimers module calls Timing.createTimer, placing a task in the MessageQueue.
When the timer fires, native code dequeues the task, looks up the module via ModuleRegistry, and calls back into JavaScript using callFunctionReturnFlushedQueue.
JS executes the callback, clears the queue, and the cycle ends.
RN JSBridge considerations
Real‑world bridges must also handle concurrency (multiple simultaneous calls) and event listening. RN uses RCTDeviceEventEmitter for event‑based callbacks instead of one‑time JS callbacks.
Unified bridge for H5 and RN
To support both H5 and RN with a single API (e.g., User.info), the bridge keeps a consistent protocol (moduleID, methodID) while allowing different call paths: RNRPCNativeModule receives the call from JS.
After processing, it emits an event via RCTDeviceEventEmitter to return results.
All other layers—protocol parsing, task dispatch, and native implementations—are shared between H5 and RN, ensuring code reuse and consistent behavior.
References
https://github.com/facebook/react-native
https://danke77.github.io/2016/12/07/react-native-native-modules-android/
https://www.cnblogs.com/fuly550871915/p/4889838.html
http://blog.cnbang.net/tech/2698/
https://github.com/sucese/react-native/tree/master/doc/ReactNative%E6%BA%90%E7%A0%81%E7%AF%87
https://www.freecodecamp.org/news/how-react-native-constructs-app-layouts-and-how-fabric-is-about-to-change-it-dd4cb510d055/
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
