DEV Community

Abinanthan
Abinanthan

Posted on

I Finally Understood React Native's New Architecture

I’ve been working with React Native for a while, but there was one thing I kept getting wrong.

I could explain what Hermes, JSI, Fabric, and TurboModules were individually.

But if someone asked me:

“Okay, what actually happens after you write <View><Text>Hello</Text></View>?”

…I couldn't give a satisfying answer.

I knew the words.

I didn't really understand the system.

So I decided to stop memorizing architecture diagrams and actually build a mental model of what is happening underneath.

This is my attempt to explain it in the simplest way I now understand it.


The diagram that confused me

You've probably seen something roughly like this:

JavaScript
    ↓
Hermes
    ↓
JSI
    ↓
Fabric
    ↓
Native
Enter fullscreen mode Exit fullscreen mode

It looks simple.

But it immediately raised a bunch of questions for me:

  • Does Hermes convert JavaScript into C++?
  • Does JSI translate JavaScript into Kotlin/Swift?
  • Is Fabric inside JSI?
  • Where does the C++ code actually live?
  • What exactly is being passed between JavaScript and C++?
  • When I change a <Text>, how does that eventually become a changed pixel on my phone?
  • And where does Node.js / Metro fit into all of this?

The more I read, the more these terms started feeling like a collection of buzzwords.

The breakthrough for me was realizing that these aren't steps in one giant translation pipeline.

They're different pieces with different responsibilities.


First: What is the New Architecture?

React Native's New Architecture isn't just "a faster bridge."

It's a broader rewrite of React Native's internals: rendering, communication between JavaScript and native code, scheduling, and native modules/components. React Native made it the default starting with React Native 0.76. (React Native)

The easiest way I understand it now is:

But this diagram can be misleading if you interpret every arrow as "code gets converted into the next thing."

It doesn't.

Let's go through it.


1. I write React code

Suppose I write:

function App() {
  return (
    <View>
      <Text>Hello</Text>
    </View>
  );
}
Enter fullscreen mode Exit fullscreen mode

At this point, I'm writing JavaScript/TypeScript and React components.

I don't write:

UIView(...)
Enter fullscreen mode Exit fullscreen mode

or:

TextView(...)
Enter fullscreen mode Exit fullscreen mode

That's the whole point of React Native.

I describe the UI using React.

So conceptually, I'm saying:

"I want a View containing some Text that says Hello."


2. Where does Hermes come in?

Hermes is the JavaScript engine used by React Native. In current React Native releases, Hermes V1 is the default JavaScript engine. (React Native)

This part was easier for me once I stopped thinking of Hermes as a React Native renderer.

Hermes' job is to execute JavaScript.

That's it.

Very roughly:

JavaScript
    ↓
Hermes
    ↓
JavaScript is executed
Enter fullscreen mode Exit fullscreen mode

Hermes can use bytecode so that applications don't have to ship only as raw JavaScript source and compile everything from scratch at startup. (React Native)

But Hermes doesn't take:

<View>
  <Text>Hello</Text>
</View>
Enter fullscreen mode Exit fullscreen mode

and magically turn it into:

UIView(...)
Enter fullscreen mode Exit fullscreen mode

That's not its job.

And this was one of my first misconceptions.


3. Then what is JSI?

This was the part I struggled with the most.

I originally thought:

JavaScript
   ↓
JSI
   ↓
C++
Enter fullscreen mode Exit fullscreen mode

meant:

"JSI converts JavaScript into C++."

It doesn't.

A much better mental model is:

JSI is an interface that allows JavaScript and C++ to interact directly.

React Native's documentation describes JSI as allowing JavaScript to hold references to C++ objects and vice versa, allowing methods to be invoked without the serialization costs of the old bridge. (React Native)

So I started thinking about JSI as a communication interface.

Something like:

┌───────────────────┐
│ JavaScript        │
│ Hermes            │
└────────┬──────────┘
         │
         │ JSI
         │
┌────────▼──────────┐
│ React Native C++  │
└───────────────────┘
Enter fullscreen mode Exit fullscreen mode

JSI isn't a box containing Fabric.

It's the interface that lets the JavaScript side interact with the C++ side.


4. Okay, but what actually gets communicated?

This was the question that finally made the whole thing click for me.

Imagine JavaScript needs to interact with some native functionality.

Conceptually:

nativeFunction("Hello");
Enter fullscreen mode Exit fullscreen mode

JSI provides the mechanism for that JavaScript code to interact with a C++ function/object.

The important thing is:

JavaScript function call
        ↓
      JSI
        ↓
C++ function/object
Enter fullscreen mode Exit fullscreen mode

We're not converting the entire JavaScript program into C++.

We're passing runtime values and function calls across the JavaScript/C++ boundary.

For example, conceptually:

JS

"Hello"
  ↓
JSI
  ↓
C++ sees a JS string value
Enter fullscreen mode Exit fullscreen mode

Or:

JS

{
  text: "Hello",
  fontSize: 20
}

        ↓
       JSI
        ↓

C++ can access those values
Enter fullscreen mode Exit fullscreen mode

This is one reason the New Architecture can avoid the old architecture's heavy serialization path. React Native specifically describes JSI as enabling direct access to JavaScript values rather than serializing everything as JSON between JavaScript and the host platform. (React Native)


5. Then where does Fabric fit?

Now we're entering the rendering side.

Fabric is React Native's new rendering system. Its core implementation moves more rendering logic into C++ and improves interoperability with the host platform. (React Native)

Let's go back to:

<View>
  <Text>Hello</Text>
</View>
Enter fullscreen mode Exit fullscreen mode

React needs to represent the UI somehow.

Conceptually, you can imagine a tree:

View
└── Text
     └── "Hello"
Enter fullscreen mode Exit fullscreen mode

Fabric maintains the rendering-side representation of this UI and handles the work needed to turn React's desired UI into changes that eventually reach native views.

The React Native architecture documentation describes this as a Render → Commit → Mount pipeline. (React Native)


6. The part that finally made sense to me: Render → Commit → Mount

This was much easier for me to understand than trying to memorize Fabric as a single word.

Imagine the screen currently says:

Count: 0
Enter fullscreen mode Exit fullscreen mode

Then I do:

setCount(1);
Enter fullscreen mode Exit fullscreen mode

React now has a new desired UI.

Before:

Text
└── "Count: 0"
Enter fullscreen mode Exit fullscreen mode

After:

Text
└── "Count: 1"
Enter fullscreen mode Exit fullscreen mode

The system doesn't need to throw away the entire screen just because one value changed.

Conceptually, the rendering process figures out:

"The Text already exists. Its content needs to change."

So the resulting UI mutation is roughly:

Update Text
text = "Count: 1"
Enter fullscreen mode Exit fullscreen mode

7. Commit

This is where I had another mental-model mistake.

I initially thought:

"Fabric renders the UI and then Mounting renders it again."

That's not really the useful way to think about it.

A better simplified model is:

Render
  ↓
Figure out the new UI state
  ↓
Commit
  ↓
Determine the mutations
  ↓
Mount
  ↓
Apply those mutations to native UI
Enter fullscreen mode Exit fullscreen mode

React Native's architecture docs explicitly describe the rendering pipeline in terms of Render, Commit, and Mount. (React Native)

So for our example:

Old:
Count: 0

New:
Count: 1

        ↓

Mutation:
Update Text → "Count: 1"
Enter fullscreen mode Exit fullscreen mode

8. And then Mounting

Now we have the actual UI mutations.

Mounting is the part that applies those changes to the host/native views.

So conceptually:

Fabric
   ↓
Commit
   ↓
"Update Text"
   ↓
Mounting
   ↓
Native Text View
   ↓
Screen
Enter fullscreen mode Exit fullscreen mode

This is where the abstract React representation eventually becomes an actual native UI update.


9. But where is all this code running?

This was another thing I wasn't clear about initially.

When I'm developing on my Mac, I have:

VS Code
Node.js
Metro
Android/iOS build tools
Enter fullscreen mode Exit fullscreen mode

These are development/build-side tools.

Metro handles the JavaScript bundling side of the development workflow.

But when the application actually runs:

📱 Phone

Hermes
React Native runtime
C++ infrastructure
Fabric
Mounting
Native platform code
Enter fullscreen mode Exit fullscreen mode

are part of the application runtime.

So I started separating my mental model into two worlds:

        💻 DEVELOPMENT MACHINE

VS Code
   ↓
Node.js
   ↓
Metro
   ↓
Build tools
   ↓
App
Enter fullscreen mode Exit fullscreen mode

and:

             📱 DEVICE

JS bundle
   ↓
Hermes
   ↓
JSI
   ↓
React Native C++
   ↓
Fabric
   ↓
Commit
   ↓
Mounting
   ↓
Native UI
Enter fullscreen mode Exit fullscreen mode

That distinction cleared up a lot for me.


10. So what actually happens when I change my code?

Suppose I change:

<Text>Hello</Text>
Enter fullscreen mode Exit fullscreen mode

to:

<Text>Hello world</Text>
Enter fullscreen mode Exit fullscreen mode

During development, roughly:

💻 My computer

Code changes
     ↓
Metro processes/bundles JS
     ↓
Updated JS is available to
the development app
     ↓
📱 Phone
     ↓
Hermes executes it
     ↓
React updates the UI
     ↓
JSI provides the JS ↔ C++ interface
     ↓
Fabric handles the rendering pipeline
     ↓
Commit determines the required mutations
     ↓
Mounting applies them
     ↓
Native Text gets updated
     ↓
📱 "Hello world"
Enter fullscreen mode Exit fullscreen mode

Notice something important here:

Metro didn't render my UI.

Hermes didn't render my UI.

JSI didn't render my UI.

Fabric is the rendering system.

And Mounting applies the resulting changes to native views.


11. The biggest misconception I had

I used to visualize React Native like this:

JavaScript
    ↓
Translate JavaScript
    ↓
C++
    ↓
Translate C++
    ↓
Swift/Kotlin
    ↓
Screen
Enter fullscreen mode Exit fullscreen mode

That mental model is wrong.

A better model is:

                 JavaScript
                     │
                   Hermes
                     │
               React logic
                     │
                    JSI
                     │
                     ▼
              React Native C++
                     │
                   Fabric
                     │
                  Commit
                     │
                  Mounting
                     │
              Native platform
                     │
                   Screen
Enter fullscreen mode Exit fullscreen mode

It's not a chain of language translators.

It's a set of systems communicating with each other.


12. And what happened to the old Bridge?

This is where the name New Architecture starts making more sense.

The old architecture relied heavily on an asynchronous bridge between JavaScript and native code.

The New Architecture removes React Native's dependency on that bridge and uses JSI for direct JavaScript/native communication. (React Native)

Very simplified:

Old mental model

JavaScript
    ↓
Bridge
    ↓
Serialize
    ↓
Message
    ↓
Native
Enter fullscreen mode Exit fullscreen mode

New Architecture

JavaScript
    ↓
JSI
    ↓
C++ / Native
Enter fullscreen mode Exit fullscreen mode

That doesn't mean "JS is magically native now."

It means the communication mechanism and the underlying architecture have fundamentally changed.


13. So what is actually "new"?

For me, the easiest summary is:

Old React Native

JS
 ↓
Async Bridge
 ↓
Serialized data
 ↓
Native
Enter fullscreen mode Exit fullscreen mode

New React Native

JS
 ↓
JSI
 ↓
C++ / Native
Enter fullscreen mode Exit fullscreen mode

plus a redesigned renderer:

React
 ↓
Fabric
 ↓
Render
 ↓
Commit
 ↓
Mount
 ↓
Native UI
Enter fullscreen mode Exit fullscreen mode

And a redesigned native module system through TurboModules.

The New Architecture also brings support for modern React features such as Suspense, Transitions, automatic batching, and useLayoutEffect, alongside the new native module/component systems. (React Native)


What I actually took away

I don't think I needed to memorize every C++ class inside React Native to understand the architecture.

The mental model that finally worked for me was:

React
│
│ "This is the UI I want."
▼
Hermes
│
│ "I'll execute the JavaScript."
▼
JSI
│
│ "I'll provide the interface between
│  JavaScript and C++."
▼
React Native C++
│
│
├── Fabric
│     │
│     ├── Render
│     ├── Commit
│     └── Mount
│
└── Native modules / components
        │
        ▼
   iOS / Android
        │
        ▼
      Screen
Enter fullscreen mode Exit fullscreen mode

And the biggest thing I learned was this:

JSI doesn't translate JavaScript into C++. It gives JavaScript and C++ a way to interact.

Once I understood that, Hermes → JSI → Fabric → Mounting stopped looking like four random buzzwords and started looking like four pieces of one system.


One thing I'm still learning

Understanding the architecture at this level doesn't mean I suddenly understand React Native's C++ codebase.

There is still a lot more to dig into:

  • How JSI actually exposes C++ functions to JavaScript
  • How Fabric's Shadow Tree works internally
  • What exactly happens during Render → Commit → Mount
  • How TurboModules use the same underlying ideas
  • How native events travel back from Android/iOS to JavaScript
  • What happens across different threads
  • And eventually, what all of this means for real-world performance

That's probably where I'll go next.

Because for me, understanding the architecture became much easier once I stopped trying to memorize the diagram and started asking:

"What is actually happening to this one piece of UI from the moment I write it until the moment I see it on my phone?"

And that's the question I'm going to keep following.


References

Top comments (0)