React Native Explained: From the Legacy Bridge to the New Architecture

Published: (February 24, 2026 at 11:42 PM EST)
8 min read
Source: Dev.to

Source: Dev.to

If you’ve been doing web development for a while, chances are you rely on React to build your front‑ends. You ship a solid web app, users like it, and then you realise you need a mobile app.

You start researching and hit a wall: you need Kotlin for Android and Swift for iOS. Do you really have to learn two separate languages, master completely different tooling, and maintain two isolated codebases?

It sounds like an absolute nightmare. But just as you’re about to give up, you stumble into the world of cross‑platform development and discover React Native – a framework that lets you write mobile apps using JavaScript and React, tools you already know, with a single codebase that targets both Android and iOS natively.

Suddenly, building mobile apps doesn’t feel like starting from zero. It feels like an extension of what you already know.

What Is React Native?

React Native is an open‑source framework that allows developers to build native mobile applications for multiple platforms (Android, iOS, macOS, Windows) using the JavaScript programming language and the React library.

  • Unlike hybrid frameworks that render inside a WebView (essentially embedding a browser inside a mobile app), React Native renders real, platform‑specific native components.

Example

Hello World

The code above does not translate into HTML.

  • View becomes:

    • ViewGroup on Android
    • UIView on iOS
  • Text becomes:

    • TextView on Android
    • UITextView on iOS

These are the same building blocks you would use if you were writing the app directly in Kotlin or Swift. Consequently, apps feel native, offering a smoother and more responsive user experience.

How Can React (a Web Library) Render Native Components?

Yes and no. The core React library is consistent across web and mobile ecosystems, but the renderer differs.

The Core Idea

  • React Core: Manages state (via hooks like useState, useEffect) and decides what part of the UI needs to be updated through reconciliation.
  • Renderer: Knows how to turn that UI description into something the platform understands (HTML DOM, Android views, iOS views).

Diagram (conceptual)

┌─────────────┐
│ React Core  │   ← manages state, reconciliation
└─────┬───────┘

┌─────▼───────┐
│ Renderer    │   ← react‑dom (web) or react‑native (mobile)
└─────┬───────┘

┌─────▼───────┐
│ Platform UI │   ← DOM nodes or native views
└─────────────┘

Renderers in Detail

RendererTarget PlatformHow It Works
react‑domWeb browsersDirectly manipulates the DOM (synchronous) because browsers understand JavaScript natively.
react‑nativeAndroid & iOSSends a description of the UI across the JS Bridge (asynchronously). The native side receives this description and creates the corresponding native components.

Key takeaway: React itself never renders anything. The renderer decides whether your components become DOM nodes or native UI views.

Diving Deeper: React Native Architecture

The Bridge (Legacy) Architecture

Also known as the Legacy Architecture, this was the default before React Native v0.76.

1️⃣ Build Phase

  1. Metro Bundler gathers all JavaScript code, React components, and assets.
  2. It produces a single, optimized file called the JS Bundle.
  3. This bundle is embedded into the native app at build time.

After the app is installed, Metro is no longer involved; everything from this point forward happens at runtime.

2️⃣ Runtime (Execution)

When the user launches the app, three threads are started:

ThreadResponsibility
JavaScript ThreadRuns the JavaScript engine (JSC or Hermes). Executes the JS bundle, holds React logic, state, and performs API calls.
UI ThreadNative UI thread of the OS. Paints the initial UI and handles user interactions.
Shadow ThreadRuns the Yoga layout engine. Calculates layout and sends instructions to the UI thread.

3️⃣ Interaction Flow (Example)

  1. User taps a button that should change the background colour.
  2. UI Thread captures the tap event.
  3. Because native UI cannot call JavaScript directly, it serialises the event into JSON and sends it across the asynchronous bridge to the JavaScript thread.
  4. JavaScript processes the event, updates state, and triggers a re‑render.
  5. The React‑Native renderer creates a new description of the UI and sends it back over the bridge.
  6. The Shadow Thread (Yoga) recomputes layout if needed.
  7. The UI Thread applies the changes, updating the native view hierarchy.

Summary

  • React Native lets you write mobile apps with the same JavaScript/React knowledge you already have.
  • The core React library handles state and reconciliation; the renderer (react‑dom vs. react‑native) decides how to materialise that UI.
  • In the legacy (bridge) architecture, a JS bundle runs on a dedicated JavaScript thread, while native UI and layout are handled on separate threads, communicating via an asynchronous bridge.

Understanding this flow demystifies why React Native feels both familiar (React) and truly native (platform‑specific UI components). Armed with this knowledge, you can now dive deeper into performance optimisations, the new Fabric architecture, or start building your first cross‑platform app!

The JS Bridge

The JS Bridge sends information to the JavaScript engine (JSC).
JSC deserializes the JSON, runs the JavaScript code (e.g., updates state with useState), and React calculates the new UI based on those changes.

The JS Thread then serializes the resulting instructions back into JSON and sends them through the asynchronous bridge.

The Shadow Thread receives this JSON, the Yoga library reads the instructions, calculates exact coordinates and properties for each element, and passes the layout information to the UI Thread, which finally paints the updated screen.

Limitations of the Asynchronous Bridge

There were several drawbacks to the original asynchronous bridge, the most significant being the bridge itself and the reliance on JSON.

1. Serialization Bottleneck

  • Mobile platforms and JavaScript cannot communicate directly, so they exchange data via JSON.
  • Stringifying and parsing JSON consumes CPU cycles, adding latency.
  • When many events are processed, this serialization/deserialization step can cause lag and frame drops on the native side.

2. Single Asynchronous Bridge

  • Every UI‑related event must travel through the bridge, even though JavaScript cannot directly modify native UI.
  • A high volume of JSON messages can congest the bridge, leading to:
    • Frame drops
    • Laggy animations
    • “Blank white screen” glitches when rendering large lists

3. Single JavaScript Thread

  • Most application logic runs on the JavaScript thread.
  • Intensive computations block this thread, degrading performance across the entire app.

Because React Native avoids blocking the main thread, all work is performed asynchronously, turning each event into a promise or callback.

The core team realized that merely optimizing the JSON bridge would not solve the fundamental performance problems, so they replaced the asynchronous bridge with the JavaScript Interface (JSI)—a C++‑based layer that calls native APIs directly, eliminating the need for serialization and message passing.

Hermes – an open‑source JavaScript engine created by Meta – is heavily optimized for React Native and uses JSI to communicate directly with native platforms. It also brings:

  • Faster Time‑to‑Interactive (TTI)
  • Smaller app bundle size
  • Reduced memory consumption

Hermes replaced the old JSC and became the default engine starting with React Native 0.70.

JavaScript Interface (JSI)

JSI is a lightweight C++ layer that lets JavaScript communicate directly with native code.

  • No message passing – the legacy bridge’s asynchronous queue is gone.
  • Synchronous calls – JavaScript can hold references to C++ host objects and invoke their methods directly.

Example

// JavaScript
nativeObjectRef.setProperty(value);   // Calls C++ method synchronously

In the legacy architecture, native modules (e.g., Bluetooth, camera) were eagerly loaded at startup, staying resident in memory even if never used. This increased launch time and memory footprint.

With Turbo Modules (new architecture), modules are lazily loaded only when required, reducing memory usage and improving performance.

Fabric System

Fabric is the new rendering system that leverages JSI and the Yoga layout engine on the native side.

In the legacy approach, rendering a large list meant serializing a massive JSON payload, queuing it, and hoping the UI thread wouldn’t drop frames—an inherently asynchronous and fragile process.

With Fabric, JavaScript uses JSI to call C++ methods that create and update native views (e.g., UIView on iOS, ViewGroup on Android) synchronously.

Fabric Render Pipeline

PhaseDescription
Render PhaseReact executes JavaScript, builds a React element tree, and uses C++ to translate it into a React shadow tree.
Commit PhaseThe Yoga library processes the shadow tree, computes exact layout coordinates, and produces a Yoga tree.
Mount PhaseThe native side renders the layout on screen based on the Yoga tree information.

The inner workings of Fabric are beyond the scope of this article and may be covered in a future post.

Summary

You now have a solid understanding of:

  • How the legacy architecture operated.
  • Why the asynchronous JSON bridge became a performance bottleneck.
  • How the React Native core team solved these issues with C++‑based JSI, Turbo Modules, and the Fabric rendering system.

What are you waiting for? Go build that app!

0 views
Back to Blog

Related posts

Read more »