DESOSA 2022

React Native: From Vision to Architecture

Main Architecture

In the beginning React, the website focused framework on which React Native is based, was advertised as the V in the Model View Controller architecture 1. However, the phrase implies that some other technology should implement the Model and the Controller. This phrasing was something Facebook already discontinued and moved away from in 2013 1. A more applicable architecture pattern or style that really defines React Native is the Container / Component pattern 2. As you might already know, almost everything within a React Native application is a component. When looking at React Native from a layered architectural perspective, it mostly resides in the presentation layer, with different possibilities for the other layers 3. For the business logic layer, something like MobX could be used within a command pattern style. Furthermore, Redux is mostly used for the database layer. As React Native is a framework for creating multi-platform applications, it allows the developers to choose their own architectural design patterns that most fit their needs 2.

Figure: Layered view of React Native Application

Container View

As React Native is a framework for other developers to create an application the containers in the container view are not as set in stone as with other software projects. Developers use only those parts they desire for their product. In the container view diagram below, some of the most used containers are displayed. On the left we can see the development stage, and on the right the compiled stage. The database is of course also accessible after the application is compiled, as well as the Cloud Platforms or the Secure Storage solutions. The React Native Directory is a library that contains many pre-build components that can be imported and used in the application. Besides that, the diagram displays two users as there is the end-user React Native developer and the end-user person who will use the final application. But as the React-Native project is a framework and not an application, the containers are not as defined as with other project. The conainers now are how a React Native application would be setup during development and not how the framework itself is setup, as that cannot be described in a containers view diagram.

Figure: Container View for React Native

Component View

As React Native is a framework it makes use of Core Components that are built-in and can be used in app development. Components are an abstraction that makes React Native platform independent. The View Component for example, is used instead of android view on Android and UIView on iOS4. However, internally React Native does access these implementations. It will handle basic interactions such as scrolling and touch input without the explicit need to program this as it is already implemented in the Component.
In general Components can be divided into six different categories5:

  • Basic Components
  • User Interface
  • List Views
  • Android specific
  • iOS specific
  • Others

The Basic Components are used to create Views, Text and Images similar to the standard HTML tags div, p and image. The UI Component offers button input, while List Views are used to load lists, as its name suggests. For the many platform specific features that both Android and iOS offer there exist seperate Components. The Core Component ActionSheetIOS can be used to display native iOS options panels. Android on the other hand has a specific Component that handles the presses for the hardware navigation buttons in the BackHandler Component. Clearly, these are OS dependent and Android specific Components do not work on iOS and neither does it the other way around. Lastly, there are Components that are not as essential for each application, such as Alerts or Status Bars.
Of course, React Native can not possibly offer all functionality natively, so many third party libraries exists that complement the Core Components.

The fact that React Native is not a typical software project, but rather a framework to build applications makes it difficult to convert its Components into a C4 component diagram, as the used Components differ per project.

Connector View

The way that React Native communicates between the JavaScript Thread and the Native Thread is through a bridge. The JS Thread is the React Native code that needs to communicate with the Native Thread that is depended on the operating system. This is for example the View Component that communicates to the android.view module. In order to send information to the bridge, it is encoded in JSON and then the bridge decodes it for the specific platform.

Figure: Illustration of React Native Bridge

This method is inefficient and will be replaced in the near future. A new JavaScript Interface (JSI) will be built that can directly communicate to the Native Thread without the need of JSON. For communication within the JavaScript Thread this serialization is not necessary.

Development View

In the react native repository. There are many folders. Most of these folders consist of functions. Like flow, scripts or keystores. These are meant for React Native development performance. There are 3 very important folders where all the components are located. The folder Libraries contains the categories of all the React components that can be used in React Native e.g Text or Flatlist. In those folders are the React class itself, but also the props and scripts that are necessary for that component. In the folder ReactAndroid are all the android functions and classes that are needed to render the android components. Most of these functions are wrappers that contain a React component and transform them to an android component. And finally there is a React folder, which is almost the same as ReactAndroid, but it contains the iOS functions and is written in c++ instead of java.

Run Time View

Since 2022 React Native has implemented a new architecture with Fabric. Fabric makes it possible to integrate more rendering logic in C++, improve interoperability with the host platform and unlock new features in React Native.6 Fabric makes it possible for the UI to create the Shadow Tree directly in C++. The renderer runs a workflow and renders the React logic on the host platform. This render pipeline consists of three phases7: render, commit and mount. In the render phase React builds a React Element Tree in JavaScript and with this Tree builds a React Shadow Tree that is in C++. Next in the commit phase it will provoke a commit that will upgrade it as the “next tree” that both the React Element Tree and the newly build React Shadow Tree will mount. Above that the layout calculation is happening in this phase. Lastly the React Shadow Tree with the calculations of layout will be converted into a Host View Tree. With this new architecture the renderer we can now have interoperability over host platforms, because of the C++ implementation.

Figure: Runtime View for React Native

How the architecture realizes key quality attributes, and how potential trade-offs between them have been resolved.

Since React Native is a developing framework all of the functionalities are meant for development. Therefore, all of the quality attributes are internal. However, those attributes affect the external attributes that are meant for the end-users. For example, the customizability attribute will make sure that the developer can customize the components. That will make sure that the components will fit in nicely in the app. But the end-user is the one who profits from that attribute in the end. The main purpose of React Native is that you only have to write the code once. This decreases the cost and time to market. But React Native is not meant for a particular operating system. It is hard to adjust all the React Native components to both android and IOS functionalities. Some functionalities that are meant for e.g Android, may be lost in the React Native code. So the functionality and performace decrease. React Native is a component driven framework, where components can be altered without affecting each other. Components can easily be used again with other React components. This is a great advantage in the sense of maintainability and reusability.

API design principles applied

React Native is a software framework that is not communicating directly with other applications over a network. If you want to call a network (REST) API to another program, you will have to implement that yourself. However, React Native uses APIs to call the libraries of the Android and iOS APIs. Examples of those APIs are the keyboard and accessibility. You can, for example, call the keyboard open and keyboard close and set the accessibility of components to true or false. Those APIs are different from those called when programmes communicate over a network. The APIs can be called by importing a library and calling the methods in the classes in that library. Those methods will then call the Android or IOS APIs. The methods are small and are named explicitly. If you want to dismiss a keyboard, you use the dismissKeyboard function.
The methods are uniformly accessible because you can import the library from any part of the code. But the interfaces of the APIs are not very clear and not all functions are documented. It is hard for a contributor to understand what the functions do in order to deliver a contribution.


  1. https://reactjs.org/blog/2013/06/05/why-react.html ↩︎

  2. https://medium.com/the-andela-way/how-to-structure-a-react-native-app-for-scale-a29194cd33fc ↩︎

  3. https://www.komododigital.co.uk/insights/react-and-react-native-design-patterns-solid-principles ↩︎

  4. https://reactnative.dev/docs/view ↩︎

  5. https://reactnative.dev/docs/components-and-apis ↩︎

  6. https://reactnative.dev/architecture/fabric-renderer ↩︎

  7. https://reactnative.dev/architecture/render-pipeline ↩︎

React Native
Authors
Zeger Mouw
Floor Straver
Caspar Meijer
Dyon van der Ende