A deep understanding into React Native’s new architecture, covering JSI, TurboModules, Fabric, and Yoga for improved performance and interoperability.
React Native’s new architecture brings significant improvements in performance, efficiency, and modularity. At its core, it introduces JSI (JavaScript Interface) for seamless JavaScript-to-native communication, TurboModules for optimized native module management, Fabric for a faster and more flexible rendering system, and Yoga for efficient layout calculations.
Together, these components modernize React Native, making it more performant, scalable, and developer-friendly. This article dives deep into how they work and why they matter.
JSI (Javascript Interface)
JSI is a lightweight, low-level bridge that replaces the older JavaScriptCore Bridge (JSC Bridge). It enables direct and synchronous interaction between JavaScript and native code without relying on serialized asynchronous calls over the bridge.
Key Features:
- Synchronous communication: Unlike the old bridge, JSI allows direct synchronous calls between JavaScript and native code.
- High performance: Avoids serialization and deserialization overhead, leading to faster interactions.
- Custom host objects: Native modules can expose C++ objects directly to JavaScript, allowing efficient operations.
- Interoperability: It works with multiple JavaScript engines like Hermes, V8, or JavaScriptCore.
How does JSI work?
JSI gives the ability to use C++ objects to communicate directly with native modules. The architecture enables bidirectional communication, meaning that JavaScript can call native code and vice versa without intermediaries.
Host Objects:
- JSI introduces
HostObject
, a C++ class that represents native objects exposed to JavaScript. - JavaScript interacts with these objects as if they are regular JavaScript objects, but the actual implementation is in native code.
class MyHostObject : public facebook::jsi::HostObject {
public:
jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override {
if (name.utf8(runtime) == "greet") {
return jsi::String::createFromUtf8(runtime, "Hello from native!");
}
return nullptr;
}
};
JSI Runtime:
- The runtime, such as Hermes or V8, acts as the execution environment for JavaScript.
- JSI runtime exposes methods to create and manipulate JavaScript values (
jsi::Value
,jsi::Object
, etc.) in native code.
Direct Function Calls:
- Native modules can register C++ functions as JavaScript functions using JSI. These functions can be invoked directly from JavaScript.
void installNativeFunction(jsi::Runtime &runtime) {
auto hello = [](jsi::Runtime &runtime, const jsi::Value &thisValue,
const jsi::Value *args, size_t count) -> jsi::Value {
return jsi::String::createFromUtf8(runtime, "Hello from native function!");
};
runtime.global().setProperty(runtime, "sayHello", jsi::Function::createFromHostFunction(
runtime,
jsi::PropNameID::forAscii(runtime, "sayHello"),
0,
hello
));
}
Custom Modules:
- Native modules are written in C++ and directly exposed to JavaScript as functions or objects using JSI.
How does data transfer work between JavaScript and native?
Data transfer in JSI happens directly using C++ objects and primitives without the need for serialization. Here’s how it works:
JavaScript to Native:
- JavaScript values (e.g.,
string
,number
,object
) are passed asjsi::Value
to the native side. - The native code can access these values using JSI APIs.
jsi::Value getNativeData(jsi::Runtime &runtime, const jsi::Value *args, size_t count) {
// Access a JavaScript number and multiply it in native
if (args[0].isNumber()) {
double number = args[0].asNumber();
return jsi::Value(number * 2);
}
return jsi::Value::undefined();
}
Native to JavaScript:
- Native code creates or manipulates JavaScript objects using
jsi::Runtime
methods and returns them to the JavaScript layer.
jsi::Object createNativeObject(jsi::Runtime &runtime) {
jsi::Object obj(runtime);
obj.setProperty(runtime, "name", "React Native");
obj.setProperty(runtime, "version", 0.71);
return obj;
}
Synchronous Communication:
- Since JSI doesn’t involve serialization, communication is instantaneous and happens directly through memory.
JSI is a game-changer in React Native’s new architecture, enabling direct and efficient data flow between JavaScript and native code. With JSI:
- Native modules can expose C++ objects and functions as JavaScript objects.
- Data is shared synchronously between JavaScript and native layers using memory references, avoiding the overhead of serialization.
This results in faster performance, lower latency, and a more flexible system for building high-performance mobile applications.
TurboModules
TurboModules are a critical component of React Native’s new architecture that leverage the JavaScript Interface (JSI) to improve how JavaScript communicates with native modules. They address the inefficiencies of the old architecture, offering better performance, modularity, and ease of integration with native code.
Key Features:
- Efficient Native Module Communication: TurboModules replace the legacy bridge mechanism with a faster and more efficient way to access native modules using JSI. Unlike the old architecture, where calls between JavaScript and native code are asynchronous and rely on JSON serialization, TurboModules allow direct, synchronous, and memory-efficient calls.
- On-Demand Loading: In the old architecture, all native modules were initialized at app startup, even if they were not used, leading to wasted memory and slower startup times. TurboModules are initialized lazily. This means they are loaded only when needed, improving app performance and reducing memory consumption.
- Cross-Language Support:TurboModules work seamlessly across JavaScript, native Android (Kotlin/Java), and native iOS (Swift/Objective-C) code, providing a unified way to integrate native functionality.
- Type Safety: TurboModules integrate with TypeScript and Flow using code generation tools, ensuring type safety and reducing runtime errors.
- Improved Debugging and Maintenance: With a well-defined interface and less boilerplate code, TurboModules make it easier to debug and maintain native modules.
How does TurboModules Work?
JSI and Host Objects:
- TurboModules utilize JSI Host Objects to expose native module functionality directly to JavaScript. A TurboModule is essentially a JSI object that represents a native module.
Code Generation:
- React Native uses a code generation pipeline to automatically generate boilerplate code for TurboModules. This ensures that the TypeScript or Flow types for the native module match the native implementation.
- Example of TurboModule interface in TypeScript:
export interface ExampleModuleSpec extends TurboModule {
add(a: number, b: number): Promise<number>;
}
Lazy Loading:
- TurboModules are registered using the
ModuleProvider
mechanism. When JavaScript requests a specific module, React Native uses theModuleProvider
to initialize and return the TurboModule instance.
std::shared_ptr<TurboModule> ExampleModuleProvider(const std::string &name) {
if (name == "ExampleModule") {
return std::make_shared<ExampleModule>();
}
return nullptr;
}
Direct Function Calls:
- Once the TurboModule is loaded, JavaScript can call its functions directly, bypassing the old bridge. These calls can be either:
- Synchronous: Immediate execution and return of the result.
- Asynchronous: Returning a
Promise
for operations that involve I/O or other non-blocking tasks.
import { TurboModuleRegistry } from 'react-native';
const ExampleModule = TurboModuleRegistry.getEnforcing('ExampleModule');
ExampleModule.add(2, 3).then((result) => {
console.log(result); // 5
});
C++ Core Layer:
- TurboModules rely on a C++ layer that acts as a common interface between the JavaScript engine and platform-specific code (iOS/Android). This makes TurboModules faster and more efficient.
Type Checking with Codegen:
- React Native generates both TypeScript/Flow definitions and native bindings automatically from a single definition file, ensuring consistency between JavaScript and native implementations.
TurboModule Workflow
- Define the Module Interface:
- The module interface is defined in a
.js
or.ts
file using TypeScript or Flow.
Example:
export interface CalculatorSpec extends TurboModule {
add(a: number, b: number): number;
multiply(a: number, b: number): number;
}
2. Code Generation:
- React Native’s build tools generate the boilerplate code required for both JavaScript and native code.
3. Native Implementation:
- The native side implements the methods defined in the module interface.
Example in C++:
class CalculatorModule : public facebook::react::TurboModule {
public:
CalculatorModule(std::shared_ptr<facebook::react::CallInvoker> jsInvoker)
: TurboModule("Calculator", jsInvoker) {}
jsi::Value add(jsi::Runtime &runtime, const jsi::Value *args, size_t count) override {
double result = args[0].asNumber() + args[1].asNumber();
return jsi::Value(result);
}
};
4. Access in JavaScript:
- Use
TurboModuleRegistry.get()
orgetEnforcing()
to access the native module.
const Calculator = TurboModuleRegistry.getEnforcing('Calculator');
console.log(Calculator.add(3, 4)); // 7
Comparison: TurboModules vs Legacy Native Modules
TurboModules are key to React Native’s new architecture, offering high performance, lazy loading, and type safety for native modules. They use JSI for fast, direct communication between JavaScript and native code, reducing overhead and boosting app speed. TurboModules also simplify native integration, making app development more efficient and scalable.
Fabric
Fabric is the UI rendering system introduced in React Native’s new architecture. Its primary goal is to improve how UI components are rendered and updated, making it faster, more efficient, and more reliable compared to the legacy system.
Key Features:
- Synchronous Communication: Fabric utilizes JSI for faster communication between JavaScript and the native UI thread, allowing synchronous updates and removing the performance bottlenecks of the legacy bridge.
- Improved Performance: Fabric optimizes rendering by batching updates, diffing trees more efficiently, and minimizing redundant computations. It uses React’s Concurrent Rendering capabilities to prioritize updates and ensure smooth UI transitions.
- Direct Host Component Access: Fabric allows React Native to directly access host components (like
View
,Text
,Image
) on the native side via JSI, improving rendering performance. - Deterministic Rendering: Fabric ensures that rendering is deterministic, meaning the state of the UI is predictable and consistent across re-renders, reducing glitches and inconsistencies.
- Cross-Platform Consistency: Fabric unifies the rendering system across iOS and Android, providing a consistent UI experience and making it easier to maintain and debug cross-platform applications.
- Event System: Fabric revamps the event system to make it faster and more responsive by handling events like gestures, taps, and scrolls more efficiently.
How does Fabric Work?
JSI Integration:
- Fabric relies on JSI to connect the JavaScript thread and the native rendering system. This enables synchronous updates and eliminates the need for serialized communication over the old bridge.
Shadow Nodes:
- Fabric introduces Shadow Nodes, which represent the UI elements in a virtual tree structure. These nodes are used to compute the layout using Yoga (explained below) before updating the native UI.
Reconciler:
- The React Reconciler works with Fabric to determine the minimal set of changes needed to update the UI. These updates are applied to the Shadow Nodes, which then propagate changes to the native view hierarchy.
Mounting Layer:
- Once the layout and rendering updates are calculated, Fabric uses its Mounting Layer to apply these changes to the native views efficiently.
Asynchronous and Prioritized Rendering:
- Fabric integrates with React’s Concurrent Rendering to allow asynchronous and prioritized UI updates, ensuring that critical updates (e.g., animations) are rendered first.
Yoga
Yoga is a cross-platform layout engine used by React Native to calculate the layout of UI components. It powers the layout system behind the scenes, ensuring that components are positioned and sized correctly on the screen.
Key Features:
- Flexbox Layout: Yoga implements the Flexbox layout system, which is widely used in React Native to design responsive UI components. It calculates how components are laid out based on their style properties (e.g.,
flex
,alignItems
,justifyContent
). - Cross-Platform: Yoga ensures consistent layout behavior across iOS, Android, and other platforms.
- Optimized for Performance: Yoga is written in C++, making it fast and lightweight. It can efficiently calculate layouts even for complex component hierarchies.
- Integration with Fabric: Fabric uses Yoga to compute the layout of Shadow Nodes before rendering them to the native view hierarchy.
How Does Yoga Work?
Input Styles:
- Developers define styles for components using Flexbox properties like
flexDirection
,flexGrow
, andpadding
.
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Hello, Yoga!</Text>
</View>
Tree Construction:
- Yoga constructs a tree of layout nodes corresponding to the UI components.
Layout Calculation:
- Yoga calculates the position, size, and alignment of each node based on its styles and parent-child relationships.
Output to Native:
- Once the layout is calculated, Fabric uses this information to update the native UI views.
Yoga supports all standard Flexbox properties, making it flexible for web developers transitioning to React Native. Ensures consistent layout calculations across platforms. Yoga optimizes layout computation by skipping unnecessary calculations and caching results where possible.
Fabric and Yoga in Harmony
Fabric and Yoga work together to handle the rendering and layout process in React Native:
Fabric handles rendering:
- Manages Shadow Nodes, event handling, and UI updates.
- Uses JSI for efficient communication with native code.
Yoga handles layout:
- Computes the layout of Shadow Nodes before Fabric applies the changes to the native views.
Final Thoughts
JSI and TurboModules revolutionize React Native by enabling faster, direct JS-to-native communication and on-demand native module loading. JSI eliminates the old bridge’s overhead, while TurboModules improve efficiency and scalability.
Together, JSI and TurboModules make React Native faster, leaner, and future-ready, paving the way for high-performance apps.
Fabric is the rendering engine in React Native’s new architecture. It improves performance, supports concurrent rendering, and ensures deterministic rendering. While, Yoga is the layout engine that calculates how components are positioned and sized using the Flexbox model.
Together, Fabric and Yoga enable faster, more reliable, and consistent UI rendering in React Native apps. Fabric focuses on rendering and communication, while Yoga handles the layout computation.
About the Author

Dhruv Harsora – Software Engineer at Simform | React, React-Native & Node.js Engineer | JavaScript Enthusiast | AI Explorer | Lifelong Learner | Problem Solver
Passionate about building scalable mobile and web applications, I specialize in React Native and full-stack development. Exploring AI and emerging tech, I love solving problems and sharing insights with the developer community.
Reference:
Harsora, D (2025). Deep Dive into React Native’s New Architecture: JSI, TurboModules, Fabric & Yoga.
Available at: Deep Dive into React Native’s New Architecture: JSI, TurboModules, Fabric & Yoga | by Dhruv Harsora | Feb, 2025 | Medium [Accessed: 1st February 2025].