Turbo Modules: Type-Safe Native Code in React Native
Turbo Modules let your JS code call native APIs synchronously, skipping the slow async bridge. Use them to access device features or high-performance native libraries.
WHY IT EXISTS React Native's original architecture communicated between JavaScript and native code over an asynchronous, serialized bridge. This was a performance bottleneck and made it impossible for JS to call a native function and get a result back immediately. Turbo Modules were created to enable direct, synchronous communication.
THE MENTAL MODEL Instead of sending a message across a bridge and waiting for a callback, Turbo Modules give your JavaScript code a direct reference to a native object. Calling a method on this object in JS synchronously executes the corresponding native code. It feels like calling a local function, not sending a request over a network.
HOW IT WORKS The process is spec-driven. First, you define the module's API in a TypeScript or Flow file. This spec acts as the source of truth. Second, you run a Codegen tool that reads your spec and generates boilerplate interface code for iOS (Objective-C++) and Android (Java). Third, you write the actual native implementation in Swift/Kotlin or Java/Objective-C, conforming to the generated interfaces. The React Native runtime then uses a C++ layer called the JavaScript Interface (JSI) to expose your native object directly to the JavaScript VM.
WHEN TO USE IT Use Turbo Modules when building new native functionality for apps using React Native's new architecture. They are ideal for performance-sensitive tasks that require synchronous access to native APIs, such as reading a device setting instantly or wrapping a high-speed native computation library. Any new library intended for the modern RN ecosystem should use them.
WHEN NOT TO USE IT If a well-maintained third-party library already solves your problem, use it. For simple, one-off native calls in older projects not using the new architecture, the legacy NativeModules system can be simpler to set up. Avoid them if you have no capacity to write or maintain native code (Swift/Kotlin/Java/Objective-C).
ONE CANONICAL EXAMPLE A common use case is creating a cross-platform persistent storage module. You would define a JS spec with setItem(key, value) and getItem(key). The Codegen would create the native interfaces. Your Android implementation would use SharedPreferences to store the data, while the iOS implementation would use NSUserDefaults. Your React Native code could then call storage.getItem('user-id') and get the value back synchronously.
Read the original → github.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.