Exploring React Native’s new architecture
Tags: reactnative
Published: 2022-05-04 19:10:59

**Written by [David Ekanem](https://blog.logrocket.com/author/davidekanem/)✏️**

In this article, we’ll explore the upcoming React Native version and the changes to the React Native architecture.

Let’s jump right into it.

## What’s happening to the React Native architecture?

A key architectural change coming to React Native is the new, native TurboModule system and the Fabric Renderer.

In the next sections, we’ll examine how these key architectural changes impact working with React Native applications by upgrading the Android Gradle plugin to be compatible with the latest nightly release version of React Native. We’ll specifically cover:

*   [Preparing an Android app for the new React Native architecture](#preparing-an-android-app-for-the-new-react-native-architecture)
*   [Exploring Fabric, React Native’s new rendering system](#exploring-fabric-react-natives-new-rendering-system)
*   [The three phases of the Fabric render pipeline](#the-three-phases-of-the-fabric-render-pipeline)
*   [TurboModules](#turbomodules)

## Preparing an Android app for the new React Native architecture

For our Android application, the following prerequisites must be met:

*   Gradle v 7.x and Android Gradle plugin (AGP) v 7.x
*   The new React Gradle plugin
*   Building react-native from Source.
*   Node.js ≥ v 14

The taste of the pudding is in the eating, so with that little quip, let’s get our hands dirty by bootstrapping a new React Native application.

```bash
npx react-native init reactNativeNew
```

Once that is done, it’s time to focus on getting our application ready to receive the nightly release of the latest version of React Native.

### Upgrading our Gradle

```gradle
cd android && ./gradlew wrapper -gradle-version 7.3 -distribution-type=all
```

The AGP version updates the top-level `build.gradle` file.

Install the new Gradle plugin:

```bash
cd ..
yarn add react-native-gradle-plugin
code android/settings.gradle
```

Edit the `settings.gradle` file to include the following lines at the end of the file:

```gradle
includeBuild('../node_modules/react-native-gradle-plugin')

if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") {
    include(":ReactAndroid")
    project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid')
}
```

Adding the Gradle plugin to our build script:

```gradle
code android/build.gradle
```

Now, add the following code block:

```gradle
buildscript {
    dependencies {
        classpath("com.android.tools.build:gradle:7.0.4")
        classpath("com.facebook.react:react-native-gradle-plugin")
        classpath("de.undercouch:gradle-download-task:4.1.2")
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
```

Edit the module-level Gradle file like so:

```gradle
code android/app/build.Gradle
```

And now, add the following code block at the top level:

```gradle
apply plugin: "com.android.application"

import com.android.build.OutputFile

// Add those lines
apply plugin: "com.facebook.react"
// Add those lines as well
react {
    reactRoot = rootProject.file("../node_modules/react-native/")
    codegenDir = rootProject.file("../node_modules/react-native-codegen/")
}
```

In the dependencies section of the `/android/app/build.gradle` file, add the below code:

```gradle
dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])

    //noinspection GradleDynamicVersion
    // replace this
    implementation "com.facebook.react:react-native:+"  // From node_modules

    // with this
     implementation project(":ReactAndroid")  // From node_modules
```

### Accessing the latest version of React Native

In order to access the most up-to-date changes to React Native, it is expected that the target application makes use of a specific nightly release. Before upgrading the app to a specific nightly release, it is recommended to first upgrade the application to the latest open source release.

```bash
yarn add react-native
```

Once the application is upgraded to the latest open source release successfully, we can target the nightly release. The below command helps with that.

```bash
yarn add react-native@0.0.0-20220201-2008-79975d146
```

Install the latest version of react-native-codegen, which is a tool for automating the compatibility between JavaScript and native code at build time, instead of at runtime.

```bash
yarn add react-native-codegen
```

With our Android application up to date with the latest version of React Native, it’s time to explore the new renderer system: Fabric.

## Exploring Fabric, React Native’s new rendering system

Fabric is React Native’s new rendering system. The Fabric renderer seeks to improve the interoperability of React Native with host platforms, which are responsible for embedding React Native in Android, iOS, macOS, Windows, etc.

### Improved communication between JavaScript and the native threads

In the current architecture, when a React Native application is run, the JavaScript code is bundled together into a package called JS Bundle, and the native code is kept separate. The JavaScript thread runs the JS Bundle, and the native/UI thread runs the native modules and handles UI rendering. The communication between the JS and native threads is enabled by a bridge, which sends data to the native threads after serializing as JSON. This bridge can only handle asynchronous communication.

With Fabric, logic is rendered in C++, which improves the interoperability between the host platforms. The Fabric renderer is implemented in C++, and the C++ core is shared among platforms, providing greater consistency and making React Native easier to adopt on new platforms.

Furthermore, the new architecture decouples the JavaScript interface from the engine, enabling the use of other JavaScript engines such as [Hermes](https://hermesengine.dev/), [V8](https://v8.dev/), or [Chakra](https://github.com/chakra-core/ChakraCore).

### Improved interoperability between React Native and host views

A host view is a tree representation of views in the host platform (e.g., Android, iOS).

![Tree Representation Of Views In The Host Platform](https://blog.logrocket.com/wp-content/uploads/2022/04/tree-representation-of-views-.jpg)

Source: [reactnative.dev/](https://reactnative.dev/)

The improved interoperability between React Native and host views is enabled by the C++ core, which is shared among different host platforms and enables React Native to render React surfaces synchronously.

It wasn’t always this way — in the legacy React Native architecture, the layout was asynchronous, which led to a [layout “jump” issue](https://github.com/react-navigation/stack/issues/366) when embedding a React Native rendered view in a host view.

![Improved Interoperability Between React Native And Host Views](https://blog.logrocket.com/wp-content/uploads/2022/04/improved-interoperability.gif)

Source: [React Navigation GitHub issue #6996](https://github.com/react-navigation/react-navigation/issues/6996)

### Improvements to data fetching

Data fetching in applications is now much more intuitive, thanks to the integration with [React Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html). Other new features available in React are now enabled in the Fabric renderer, such as the new [Concurrent Features](https://github.com/reactwg/react-18/discussions/4) available in React 18\. This includes the [`startTransition`](https://github.com/reactwg/react-18/discussions/41) feature, which keeps the UI of our applications responsive during expensive state transitions.

Server-side rendering is also made easier with the new renderer.

## The three phases of the Fabric render pipeline

The render pipeline occurs in three phases:

1.  The Render phase
2.  The Commit phase
3.  The Mount phase

Let’s look into each of them more closely.

### The Render phase

In this phase, React executes product logic to create React element trees, which consist of React elements. A React Element is a plain JavaScript object that describes what should appear on the application screen.

The React element tree is used to render the React shadow tree in C++. The React Shadow Tree is created by the Fabric Renderer and consists of React shadow nodes, which are objects that represent the React host components that are to be mounted, and contains props that originate from JavaScript.

```js
const App = () => {
  return (
    <View>
      <Text>App.js</Text>
    </View>
  );
};
```

In the Render phase, as each React element is invoked, the renderer synchronously creates a React shadow node. Take note that this synchronous creation of a React shadow node only occurs for React host oomponents, and not for [React composite components](https://reactnative.dev/architecture/glossary#react-composite-components). When translated into a React Shadow Block, the above code would see the `<View>` translated into a `ViewShadowNode` object.

A great thing about the new renderer is that any parent-child relationship between React element nodes will correspond to the relationships among React shadow nodes. The above process shows how the React shadow tree is assembled; once the React shadow tree is complete, the renderer triggers a commit of the React element tree.

Below is a visual representation of the render phase:

![Visual Representation Of The Render Phase](https://blog.logrocket.com/wp-content/uploads/2022/04/the-render-phase.png)

Source: [reactnative.dev](https://reactnative.dev)

### The Commit phase

The cross-platform layout engine [Yoga](https://yogalayout.com/) is hugely important in handling operations that happen during the commit phase, which consists of two operations: layout calculation and tree promotion.

The layout calculation calculates the position and size of each React shadow node. This is achieved by invoking Yoga to calculate the layout of each React shadow node.

Once the calculation determines the amount of available space, the `Tree Promotion` operation promotes the new React shadow tree as the next tree to be mounted. This promotion represents the latest state of the React element tree.

![The Commit Phase Diagram](https://blog.logrocket.com/wp-content/uploads/2022/04/the-commit-phase-1.png)

Source: [reactnative.dev](http://reactnative.dev)

### The Mount phase

This is the phase in which the React Shadow Tree (which contains the data from the layout calculation) is transformed into a host view tree with rendered pixels on the screen. The Fabric renderer creates a corresponding host view for each React shadow node and mounts it on screen.

![The Mount Phase Diagram](https://blog.logrocket.com/wp-content/uploads/2022/04/the-mount-phase.png)

Sources: [reactnative.dev](https://reactnative.dev/architecture/xplat-implementation)

## TurboModules

The TurboModules system is an enhancement of [Native Modules](https://reactnative.dev/docs/native-modules-intro). In their current architecture, a [table](https://github.com/facebook/react-native/blob/1151c096dab17e5d9a6ac05b61aacecd4305f3db/ReactCommon/cxxreact/ModuleRegistry.cpp#L70) holds the module registry, and when the JavaScript code calls a specific native module, the indices of the module and the methods are passed to Java/ObjC, which invoke the specific methods.

A proposed solution to the eager initialization of Native packages is the use of the [`LazyReactPackage`](https://github.com/facebook/react-native/blob/42146a7a4ad992a3597e07ead3aafdc36d58ac26/ReactAndroid/src/main/java/com/facebook/react/LazyReactPackage.java), but this is not an effective method because the annotation processor [`ReactModuleSpecProcessor`](https://github.com/facebook/react-native/blob/42146a7a4ad992a3597e07ead3aafdc36d58ac26/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java) does not run with Gradle; hence, the `LazyReactPackage` doesn’t work with the open source release.

With the new implementation, JavaScript will expose a top level Native Module Proxy, called `global.__turboModuleProxy`, to access a native module. If we used the example of `"SampleTurboModule"`, the application code will call the `require('NativeSampleTurboModule')`. In the `NativeSampleTurboModule`, the [`TurboModuleRegistry.getEnforcing()`](https://github.com/facebook/react-native/blob/7fbccdea22993b56988685174492583b16dc69db/Libraries/TurboModule/TurboModuleRegistry.js#L28) function is called, which holds a reference to the Native Modules and then calls `global.__turboModuleProxy("SampleTurboModule")`.

This triggers the JSI function and a [getModule](https://github.com/facebook/react-native/blob/7fbccdea22993b56988685174492583b16dc69db/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/TurboModuleManager.cpp#L56) function is invoked, which is defined for Java and ObjC, and returns a JSI object for the specific TurboModule (i.e., `GeoLocation`, `FileStorage, DeviceInformation`) that previously would have been initialized at app startup. This allows JavaScript code to load each module when it is required, instead of initializing them before the app is opened.

## Summary

The React Native next version promises an improvement in startup time, and developer experience, with improved interoperability between all threads, a new web-like rendering system(Fabric). A key aspect that excites me about the new architecture, is the ability to easily build applications for Smart TVs.

---
##[LogRocket](https://www2.logrocket.com/mobile): Instantly recreate issues in your React Native apps.

![LogRocket React Native monitoring solution](https://blog.logrocket.com/wp-content/uploads/2021/10/react-native-plug_v2-2.png)

[LogRocket](https://www2.logrocket.com/mobile) is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your React Native apps — [try LogRocket for free](https://www2.logrocket.com/mobile).