Traditional React Native applications relied on the JavaScript Bridge for communication between the JavaScript realm and native host platforms (iOS/Android). While functional, this bridge introduced overhead through asynchronous JSON serialization and deserialization, leading to performance bottlenecks and latency, especially during complex interactions or frequent calls. The JavaScript Interface (JSI) directly addresses this. JSI is a lightweight C++ layer that allows the JavaScript runtime (like Hermes or JSC) to directly hold references to C++ host objects and invoke their methods. This fundamental shift bypasses the bridge entirely, establishing a direct, synchronous communication channel that’s significantly faster and more efficient.
TurboModules are the next evolution of React Native's Native Modules, built upon the power of JSI. They were designed to overcome the limitations of the old bridge by leveraging JSI's direct access capabilities. Key benefits of TurboModules include lazy loading (modules are loaded only when needed, improving app startup time), type safety (achieved through code generation that creates strongly typed interfaces), and, critically, the ability to perform synchronous native calls. With JSI, a JavaScript function can directly call an exposed C++ method and immediately receive its return value, much like calling another JavaScript function. This eliminates the need for Promises or callbacks for operations that demand instant results.
Practically, synchronous native calls are invaluable for quick, non-blocking operations where an immediate result is crucial and the overhead of an asynchronous roundtrip would be detrimental. Think about querying simple system states like the current UI theme, checking a specific hardware capability, or performing a very fast calculation directly on the native side. However, a significant caveat applies: synchronous calls block the JavaScript thread. Prolonged or complex synchronous operations will freeze your UI, leading to a poor user experience. Therefore, they must be used sparingly and only for operations guaranteed to complete almost instantly. For longer-running tasks, network requests, or I/O operations, asynchronous patterns (Promises, callbacks) remain the best practice to keep your UI responsive and fluid.
Key Takeaways
- JSI enables direct C++-JavaScript communication, bypassing the old bridge entirely.
- TurboModules leverage JSI for enhanced performance, lazy loading, type safety, and synchronous native calls.
- Synchronous native calls block the JavaScript thread; use them sparingly for quick, non-UI-blocking operations.
- Most native operations should remain asynchronous to ensure a responsive and smooth user interface.
Code Example
How this code works
This code demonstrates how React Native applications interact with platform-specific native code (e.g., Swift on iOS or Kotlin on Android) using TurboModules and JSI, specifically illustrating both synchronous and asynchronous approaches for calling native functions. The code first defines an interface, MySystemInfoType, to clearly specify the methods available on a native module called MySystemInfo. This module is then accessed via NativeModules.MySystemInfo, with its type asserted to ensure TypeScript correctly understands its capabilities.
The MySystemInfo.getThemeSync() call demonstrates a synchronous native operation. This means the JavaScript code execution pauses until the native method completes and returns a value, like 'light' or 'dark', directly. A subtle but critical detail for beginners is that synchronous native calls can throw JavaScript errors directly if the native side encounters an issue, making the try...catch block essential for robust error handling. In contrast, MySystemInfo.getDeviceId() is an asynchronous native call. It immediately returns a Promise, allowing JavaScript execution to continue without waiting. The actual device ID is then retrieved later using .then() once the native operation finishes, with errors handled through Promise rejections rather than direct throws.