React Native’s new design is a big improvement over the old way it worked. Instead of using a slow "bridge" to talk between JavaScript and native code, it now uses a faster system called JSI (JavaScript Interface). It also adds TurboModules and a new way to draw screens called the Fabric Renderer.
Thanks to these updates, apps run faster, look more consistent, and can connect better with native features (like camera or GPS). This document explains the different layers and how the parts of a modern React Native SDK work together using this new system.
Old Architecture vs New Architecture
Layered Architecture Overview
App Layer (Top Layer)
This is where you write your app using JavaScript or TypeScript.
You use React components (, ) to build your UI.
All your business logic (how your app works) is written here.
React Runtime + JSI Layer (Middle Layer)
This is the engine that runs your JavaScript code.
It uses a JavaScript engine like Hermes or JavaScriptCore.
JSI (JavaScript Interface) helps JavaScript talk directly to native code (like a translator that speaks both languages).
It also uses TurboModules to connect to native features (like camera, battery).
Think of it as a smart brain that handles all the logic and knows how to ask the device(phone) to do things.
Rendering & Bridge Layer (Fabric + UI updates)
This is where your app’s UI is turned into real screens on the phone.
The Fabric Renderer takes the React components and turns them into native views.
It draws everything smoothly and efficiently, using Yoga, which is a layout engine that supports flexbox (just like CSS).
It’s like an artist who paints your app on the phone’s screen, very quickly.
Native Platform Layer (Bottom Layer)
This is the layer that talks directly to the phone's operating system (Android or iOS).
Here, code is written in Kotlin/Java (Android) or Swift/Objective-C (iOS).
It handles hardware features like camera, location, notifications, etc.
Think of this as the hands of your phone, doing the actual work.
Summary Table
Simple Step-by-Step Sequence: "User Taps a Button”
User taps the screen (UI event)
- The user touches a button () on the phone screen.
- This touch event is handled by the native OS (iOS or Android).
Example: Finger touches a real native button.
Native system sends the touch event to React Native
- The OS (Android/iOS) sends the event to the React Native runtime via the native event system.
- The Fabric Renderer listens for UI events at the native level.
The native side says, “A tap just happened on this view.”
Fabric passes event to the JS Runtime via JSI
- Fabric identifies which React component was tapped.
- It sends that event through JSI to the JavaScript engine (Hermes).
- No need for the old bridge — this is fast and direct.
Event goes from C++/Fabric into JS via JSI.
React Runtime processes the event
- Your JavaScript function (like onPress={() => ...}) gets called.
- React may re-render the component if the state/props change.
Your app logic runs: “If button was pressed, do X.”
UI update (if needed) is sent back to native via Fabric
- If your button tap causes a UI change (like showing a new message), React will rebuild the virtual tree. -Fabric compares the new tree with the old one (diffing). -Then it updates the native views directly through C++.
Native screen is updated to show new UI (e.g., a message appears).
Layered Pseudocode: Button Tap Flow
User Layer (JS - App Layer)
function MyApp() {
const handlePress = () => {
console.log("Button tapped");
setState("Show Hello Text");
};
return (
<View>
<Button title="Tap Me" onPress={handlePress} />
{state === "Show Hello Text" && <Text>Hello World</Text>}
</View>
);
}
User taps the button → onPress is called.
JS Runtime & JSI Layer
// JSI bridge exposes the button event handler
installJSFunction(runtime, "handlePress", []() {
// This is called by Fabric when a native event comes in
jsRuntime.invoke("handlePress"); // Calls the JavaScript function
});
Uses JSI to invoke JS function directly from C++ without serialisation.
Fabric Renderer Layer (Native C++)
// Native event dispatcher detects tap on button view
void onTouchEvent(ViewID id) {
if (id == buttonViewID) {
auto event = createPressEvent();
dispatchEventToJSI(event); // Send to JS through JSI
}
}
// After JS function runs and UI state changes...
void reconcileChanges(ReactTree newTree) {
auto diff = diffTrees(oldTree, newTree);
applyNativeChanges(diff); // Update UI using native view managers
}
Handles touch detection, tree diffing, and UI updates.
Native Platform Layer (iOS/Android)
// Android View Manager or iOS UIView updates UI
fun updateNativeView(componentId, newProps) {
when (componentId) {
"TextView" -> textView.setText(newProps.text)
"ButtonView" -> button.setTitle(newProps.title)
}
}
Native components (e.g., TextView, Button) get updated with new props.
Conclusion
React Native’s new SDK architecture is a big improvement over the old one. It replaces the slow and complex "bridge" with a faster system using JSI, TurboModules, and Fabric. This new setup lets JavaScript and native code talk to each other directly, without converting everything into messages. As a result, apps start faster, run smoother, and respond more quickly to user actions. For developers, it also makes it easier to build powerful features that work well on both Android and iOS. Overall, this new architecture makes React Native apps feel more like real native apps while still using JavaScript.
Top comments (0)