The road to the production of a React Native application is long and full of pitfalls: implementation of the build, signature of the application, deployment on the stores, and this for each platform! Several tools are required for this deployment system: fastlane, a CI with macOS runners, firebase, each requiring its own configuration. This configuration, which requires several days as well as in-depth knowledge in mobile development, does not automatically guarantee an efficient deployment system: the build time on iOS is long, up to half an hour, without complex build optimization. To simplify the implementation of an effective deployment system, Expo created Expo Application Services.
EAS combines several tools in one, making it possible to build and deploy React Native applications more quickly, easily, and at a lower cost:
We estimate that EAS costs an average of $100 per month for a medium-sized project, but is also available for free with a waiting time.
OUR POINT OF VIEW
We highly recommend using EAS. Its configuration is quick and easy to set up, making it a great option, especially for developers with less experience in the mobile field. By opting for EAS, you will save time and be able to focus fully on the essentials: the development of your application.
HISTORY 2022
It's a new blip this year.
The world of mobile development can be daunting for developers new to this field. Indeed, they will face build, signature, and deployment issues, which require mobile-specific knowledge. React Native also brings its share of challenges, with complex updates and complicated bridges to implement.
In recent years, The Expo framework provides solutions to problems encountered by React Native developers. The latter consists of several parts that can be useful depending on the needs of your projects:
However, if the native changes in your project are complex or numerous, using custom plugin and Prebuild systems may make these changes more expensive to develop and maintain. In this case, we recommend versioning your native files, and adopting a “bare workflow” development; whatever your case, you can take advantage of the libraries of the SDK Expo and the CLICK.
At the end of our last Tech Radar, we issued two warnings about using Expo:
As a backup solution, it is now possible to build and deploy your application locally. These improvements allow us to switch Expo to “Adopt”. So any React Native project can take advantage of the different parts of Expo according to its needs.
OUR POINT OF VIEW
For new projects, we recommend starting by using all the parts of Expo that meet the needs of your projects, to abstract maximum complexity for as long as possible. If at some point an Expo tool no longer meets your needs, you can eject it.
HISTORY 2022
Trial - See the Tech Radar 2022
App startup time has long been a problem with React Native, especially on low-end Android phones. For example, one of our apps, which contained significant JS code, started up in 12.9s on a low-end phone.
To address this problem, Facebook has implemented Hermes, a new JavaScript engine. Instead of parsing and compiling the JS into binary code when the app is launched (like a traditional JS engine), Hermes does this during the app's “build time”.
Thus, an application under Hermes no longer includes an embedded JS file, but rather a binary code file. The results are striking: thanks to the use of Hermes, the application mentioned above now launches in just 3.9 seconds and the startup time of all our apps has been reduced by at least half. Setting enableHermes to true in the configuration and adding a few polyfills (e.g. i18n, regexp) will allow you to take advantage of this improvement.
Some features are still missing (such as some internationalization APIs) and may require the addition of a polyfill. But the list is limited: for example, the regex capture groups mentioned in the previous edition of this tech radar are now supported.
Hermes has now been activated by default on iOS and Android since version 0.70.0. However, according to the Software Mansion study “State of React Native 2022", Hermes is still only adopted by 60% of teams.
OUR POINT OF VIEW
For projects started without Hermes, we recommend that you migrate to activate it. The benefits outweigh the costs, because without Hermes, the startup time of your Android apps is unlikely to match Google's recommendations.
HISTORY 2022
Adopt - See the Tech Radar 2022
Modern web browsers allow developers to store key-value data locally on the user's computer using the API LocalStorage. React Native took inspiration from this API to provide a similar API, called asyncStorage.
However, unlike its synchronous web counterpart, asyncStorage has an asynchronous API due to the use of the React Native bridge. However, in most use cases of asyncStorage in our applications, synchronization would be preferred. asyncStorage requires us to use JavaScript Promises, which makes it difficult to persist and hydrate the state when the application starts.
Fortunately, a serious alternative to asyncStorage exists: react-native-mmkv.
This library is a native module that uses the powerful MMKV technology, a native key-value data persistence framework, developed by Tencent.
The benefits of react-native-mmkv are numerous:
OUR POINT OF VIEW
We therefore recommend that you use react-native-mmkov as a solution for persisting your key/value data for your React Native projects, and we invite you to plan a migration plan from using AsyncStorage to react-native-mmkov.
HISTORY 2022
It's a new blip this year.
Making animations in React Native is not trivial. While the Animated API (provided with React Native) is simple, the code is imperative and makes the components more complex. Since the implementation cost is high, animations are often not given priority in application development.
The Reanimated library is changing the game by offering a more declarative approach to animations. Animations are simple to implement and do not affect the readability of the component code. Animations are executed in the UI thread, which ensures smooth animations and good performance.
For more complex animations, Reanimated hooks allow blocks of animation code to be easily extracted into separate hooks, allowing reuse and simplified maintenance. Even better, the Layout Transitions in the library make appearing, disappearing or changing animations more simple and intuitive. These tasks would have been very complex to perform without the use of this library.
Reanimated greatly improves the quality of the animation code compared to Animated by React Native, while encouraging developers to implement animations. The library is actively maintained and its stability has improved significantly over the months. Version 3 includes performance and quality improvements, as well as support for the new React Native architecture and shared element transitions. Reanimated is now a pillar of the technical stack of a React Native project.
OUR POINT OF VIEW
We recommend using version 2 if your dependencies are incompatible with version 3 (using the V1 legacy api), version 3 otherwise.
HISTORY 2022
Trial - See the Tech Radar 2022
Like all JavaScript projects, React Native projects need a package manager to install and update the dependencies they use.
Version 2 of yarn was launched in 2020 with an ambitious goal: to make “zero-installs” possible, with which a git “checkout” is enough to have the right packages installed, without an installation step. This feature replaces the folder node_modules by a mechanism called Plug-n-Play (PnP).
In practice, this mechanism has not been widely adopted because it requires specific integration in each tool (nodejs, bundlers, IDE, TypeScript, etc...). For example: metro, the React Native bundler, does not currently manage PnP, which has therefore blocked the adoption of yarn 2 by React Native teams. However, yarn 3 has re-introduced a “classic” mode of operation with a folder node_modules.
This allows yarn 3 to be used with React Native (by adding a configuration line) nodeLinker: node-modules) and to benefit from its other advantages:
OUR POINT OF VIEW
With symlink support that recently arrived in metro, the pnpm manager package could become a good alternative, but yarn 3 is still the best option for React Native projects today. We use it on our projects and the transition went without any difficulties.
HISTORY 2022
It's a new blip this year.
Over the past five years, TypeScript has significantly changed the JavaScript landscape, even becoming one of the top five most used languages in 2022, according to the stack-overflow survey. The promise of TypeScript is to ensure that if the input data is correct, so will the output data. However, this raises several questions:
La Zod Bookstore offers a solution to this problem by making it possible to generate associated types and validators from a data schema. These validators make it possible to ensure that the data received corresponds to the type expected by the application and protect the application against poorly formatted data.
The use cases for Zod are multiple:
However, using Zod has a disadvantage: the library requires a lot of knowledge to be used effectively. While senior developers can use it effectively, it can complicate the integration of junior developers. However, the library can be adopted incrementally, which facilitates its adoption within teams.
OUR POINT OF VIEW
In our previous radar, we recommended the use of Runtypes, a competing library offering similar functionalities. However, we have encountered compatibility issues with the Hermès JavaScript engine. Additionally, we have
found that Zod was more complete and better maintained than its competitor. That's why Zod has become the library that we use by default on our projects, and we recommend that you do the same.
HISTORY 2022
It's a new blip this year.
React Query has gradually established itself as a reference solution for managing asynchronous calls and server state in React applications. In fact, we positioned it in “Adopt” in our previous edition of the radar.
However, even with React Query, code can become complex when asynchronous calls multiply within the same page and you want to keep detailed management of loading and error states. These calls should be made (with useQuery) where you want to display the loader (e.g. at the level of a page component) rather than in the component that needs the data. The components are becoming less reusable.
As of React 18, Suspense is no longer an experimental feature and solves this problem. We replace the conditions if (isLoading) by a component <Suspense>, positioned anywhere, higher up the component tree. React then manages the display of the loader or content. A similar feature exists for errors with “Error Boundaries”.
React Query offers compatibility with Suspense on an experimental basis. Simply set up the React Query client with Suspense: true. Activating this option allows you to benefit from the advantages of Suspense today, from organizing the code to the division of components.
Note that:
OUR POINT OF VIEW
It's entirely possible to activate Suspense today on new projects (the cost of migrating from current APIs to future changes will be lower than without Suspense), but for existing projects, it's best to wait before starting a migration.
HISTORY 2022
Adopt - See the Tech Radar 2022
To display a long list of items like a news feed, React Native offers FlatList, which allows you to virtualize the display: only a portion of the list is rendered on the screen and is updated dynamically as the user scrolls, guaranteeing better performance.
However, by default, the FlatList render enough elements to fill 21 screens (yes, that's huge!) , which is expensive. In addition, on the scroll, the FlatList will go through all the displayed items to re-render them if they are indeed in the view. Aggressive storage limits the impact on performance, which will however fall short of native components like the Android RecyclerView.
FlashList Shopify's is an alternative solution that addresses these performance issues:
The gains are obvious: CPU consumption per scroll is halved on the majority of our projects!
Migrating from FlatList to FlashList seems simple in theory: you only need to change two letters! In practice, the items on the list may require adaptation in complex cases. Understanding how recycling works adds complexity (e.g., it is not recommended to have a state specific to the items in the list). In addition, we met a few problems with RTL support, which can be a hindrance to using FlashList. It should also be noted that web support is still in beta.
OUR POINT OF VIEW
We recommend implementing the migration from FlatList to FlashList to take advantage of significant performance gains, while conducting non-regression tests to avoid falling into edge cases that are not supported by the library.
HISTORY 2022
It's a new blip this year.
Formatting in React Native can be slow and tedious. Using stylesheets or a library like Styled Components can be slow and does not guarantee consistent styles throughout the code. On the web, Utility First Styling has become a common method for accelerating and improving formatting, with Tailwind being the most popular example of this concept.
The idea of Utility First style is to abstract the common stylization that you would do in “utility classes”. For example, if you want to add a padding of 4 rem, you would have a p-4 class to handle this feature. Another example could be to completely round off the corners of a div, so you would have a rounded-full class to handle this feature. Using the “Utility First” style means that you need to combine these classes to completely style your components.
Since Tailwind is a solution designed primarily for the web, a few libraries support Tailwind for React Native:
We chose to include Tailwind in our “trial” dial this year because it is widely used on the web and has been tested and approved over the past few years.
On the mobile side, we believe that NativeWind has reached a sufficient level of maturity to use it calmly as a Tailwind implementation for React Native.
OUR POINT OF VIEW
We recommend using NativeWind, as it offers the lowest discrepancy from the original Tailwind library and a Babel plugin to replicate the Tailwind React implementation. NativeWind is actively maintained, supports RN for the web, and offers numerous features such as dark mode, arbitrary classes, media queries, themes, custom values, and plugins.
HISTORY 2022
It's a new blip this year.
One of the biggest advantages of React Native is being able to share the same code between 2 or even 3 platforms (Android, iOS, Web...). But if you have an existing native application with a significant codebase, how do you take advantage of it?
Rewriting everything from scratch would be too risky: you can only test in production at the end of a long redesign. So-called “brownfield” applications are applications that, while maintaining their “legacy” codebase, in this case their native codebase, gradually migrate to the new technology, React Native, thus making it possible to put into production little by little. React Native now has a documenting for this purpose. But if native developers continue to maintain the native part of the app in parallel with the migration to React Native, the configuration that this implies will be disruptive for them. Indeed, Node is then necessary to launch the application and metro must run in parallel with the native app to serve the JS (like a usual React Native app). Also, like React Native and the associated libs (like Reanimated or react-native-webview) incorporate significant native code, the native build time is extended since these dependencies will often be recompiled. On our last Brownfield project, iOS build time was increased by 30 to 50% depending on the developer machines.
The alternative is to package React Native, the required libs, and the JavaScript code into a third-party SDK: distributed as a .aar for Android or a .xcframework on iOS. Thus, integration into the native app is simple: the RN part is activated and used like any native third-party lib.
In addition, as the code is pre-compiled, the impact on build times is negligible. Note that Walmart had developed Electrode to industrialize this process, but the solution is currently poorly maintained and potentially cumbersome for smaller teams than those at Walmart.
On the other hand, it becomes more complicated to develop at the same time on the native part and the React Native part of the app. Interfacing contracts between the native part and the React Native SDK must therefore be clearly defined beforehand.
This integration is also more complex than that recommended by the documentation and requires real native expertise. For example, we had to modify the RN Gradle plugin to ensure the activation of Hermes.
OUR POINT OF VIEW
We therefore recommend that you ensure that you have a native team of sufficient size and the necessary expertise before choosing this solution.
HISTORY 2022
It's a new blip this year.
Since an app is often available on both the web and mobile, it's natural to want to share code between these platforms, which is possible for business logic, UI state, and API calls. However, UI components cannot be shared by default.
React Native Web is an implementation of React Native components and APIs that is compatible with React DOM.
Its installation is simple, all you have to do is install react-native-web as a dependency of the web app and add an alias from react-native to react-native-web in the bundler configuration. This allows you to import React Native components into a React web app.
We have been able to share between 75% and 95% of the code between web and mobile using React Native Web on several projects, and our feedback is very positive.
In our previous radar, we reported a risk linked to the maintenance of the library by a single developer: Nicolas Gallagher. Hired by Meta since, he has initiated a job ofunification of web and native APIs. However, in talking to our teams or other teams that have chosen to use RN for Web, we noted some points that are often underestimated:
OUR POINT OF VIEW
While React Native Web is moving in the right direction, accessibility trade-offs and challenges faced by some teams prevent us from fully recommending it at this stage.
HISTORY 2022
Trial - See the Tech Radar 2022
Metro has been the default bundler for React Native since 2017. It provides interesting features (Live Reload, Hot Reload, build optimized for React Native) and meets the needs of a large number of projects. However, it has some limitations:
React Native benefits from innovations in the web ecosystem and Metro is being questioned by other bundlers:
OUR POINT OF VIEW
These tools and libraries challenge the monopoly established by Metro, but are still very experimental and require advanced knowledge in JavaScript bundling to be configured and used on large production projects. However, they may meet some of your needs that are not compatible with Metro.
HISTORY 2022
It's a new blip this year.
Announced in 2018, the new React Native architecture is finally available and activable. It now allows:
To migrate to this new architecture, simply change a configuration parameter in your app, provided that all the libraries in your projects support this new architecture. The list of missing bookstores has declined since our last edition, but some major bookstores like react-native-vision-camera or Flashlist are still asking for work.
In our previous Tech Radar, we saw long builds (5 times longer than the duration without the new architecture), which has been fixed since version 0.71. Hermes and React Native are now no longer compiled from source code, but distributed as pre-compiled artifacts on Maven Central. In version 0.72.0, Meta fixed regressions performance that we reported. Additionally, improvements have been made to the documentation to facilitate the migration of existing apps and libraries. In version 0.70.0, the “auto-linking” feature was added for libraries.
On the other hand, some of React 18's concurrency features like UseDeferredValue don't seem to impact performance as positively only on React Web.
OUR POINT OF VIEW
This new architecture is not yet ready to be activated on your apps, but it is the future of React Native. We therefore recommend that you analyze the list of libraries you use and check that a migration plan is in progress for each of them, in order to prepare for the future. In fact, we hope to be able to switch the new architecture to “Adopt” in our next Tech Radar.
HISTORY 2022
It's a new blip this year.
Navigating React Native was a major challenge for developers. While React Navigation has established itself as the reference navigation library in RN, it can be tricky to use and cause performance issues. Routing best practices are difficult to define, especially for universal apps that work on both native and web platforms.
Expo Router aims to simplify this process by isolating some of the complexities of React Navigation and standardizing navigation. using file system based routing (FSR), which has become a standard in web development thanks to frameworks like Next.js
This differs from the declarative approach taken in React Navigation, where you define browsers in your code. Ex: where you would have <Stack.Screen name="home” component= {homeScreen} />
in React Navigation, to add a home screen, you would create a file home.ts inside the app directory with Expo Router.
Expo Router offers several advantages, including: the automatic creation of deep-links, the application of best practices thanks to the FSR and automatic compatibility with universal apps (native and web). This has a significant impact on the resolution of some traditional navigation-related challenges. Overall, Expo Router's features simplify the process of deep linking and the smooth transition between web and native.
OUR POINT OF VIEW
Given its relative novelty, there is still room for the maturity and improvement of components such as documentation and the stability of TypeScript support. We left Expo Router in the “assess” category. Therefore, we recommend keeping an eye on Expo Router as over time it may become a preferable solution to React Navigation.
HISTORY 2022
It's a new blip this year.
The performance of mobile applications is a major challenge to improve user retention. For React Native applications, approximately 80% of performance issues come from JavaScript code. Performance regressions are among the hardest to detect, and end users are often the first to report them.
E2E tests can be used to address this problem. However, they are expensive to set up, take a long time to execute and do not allow the performance of components to be tested in isolation.
Callstack offers us a new solution with its library Reassure. Reassure works by using react-native-testing-library to perform performance tests on React Native components. It measures and compares component rendering times between different git branches in order to detect regressions.
Reassure has key benefits:
Despite its numerous advantages, Reassure has some limitations. It does not absolutely evaluate the performance of the component, so a performance problem as soon as the component is created will not be detected. It is not compatible with jest-expo, and the technology is still young and evolving rapidly.
OUR POINT OF VIEW
After an initial proof of concept phase, we decided to deploy Reassure on some of our projects. We believe that this technology will continue to grow in popularity and efficiency and we recommend that you test it out.
HISTORY 2022
It's a new blip this year.
Universal apps that work on both the web and mobile have grown in popularity. However, many of the existing libraries (e.g. React Native for Web) in this area only deal with basic problems. So developers have to deal with more complex UI differences, such as component behaviors and layouts. For example, managing button states on the web vs. mobile may require double pressing the buttons natively. Mobile apps use stacks and tabs for layouts, while web apps use multi-column layouts to take full advantage of real screen space.
Tamagui is a comprehensive UI kit that provides a consistent style while sharing tokens, themes, fonts, and more across the web and native platforms. It's a lightweight style engine, with themes, animations, responsive, pseudo-styles, and performance optimizations, to flatten the component tree with partial evaluation. It produces a minimum of CSS and styles in RN. In addition, it provides pre-built components that can be used on the web and mobile, both for common elements (e.g. buttons) or more complex (e.g. layouts) with web or mobile-specific implementations depending on the target.
Tamagui separates implementations while unifying APIs, allowing components to appear and behave differently on the web and on mobile.
It is a powerful approach, which offers a native experience depending on the platform, although imperfect: some components and elements of the UI library maintain a “web-first” or “mobile-first” appearance and behavior. However, in most cases, the compromises made are judicious and pragmatic.
We recommend considering Tamagui for an app that was first designed for mobile and for which it is impossible to manage a separate web app. Tamagui can be a powerful tool for creating universal apps from a single codebase.
OUR POINT OF VIEW
At this point, we have chosen to place it in the “assess” category, as it is not yet used in production in any of our projects. Although it is supported by Vercel and has a large number of stars and contributors, it comes with few guides that are accessible to beginners, to reach a wider audience.
HISTORY 2022
It's a new blip this year.
API calls pose a significant typing challenge, making it difficult to detect breaking changes. Various solutions have been proposed, such as sharing types between frontend and backend, using GraphQL, OpenAPI with codegen, or gRPC with Protobuf. However, these solutions can add complexity to a codebase as well as a significant workload.
TrPC takes an interesting approach to get typesafety between the front and the back, using TypeScript. With TrPC, you can create and consume APIs that are completely type-secured, without the need for schemas or code generation, eliminating issues with API contracts.
Among the main features of TrPC are static type security and autocompletion for client inputs.
He has become well known in the community for his excellent development experience. Additionally, numerous resources and tutorials are available online, thanks to the popularity of the library, making it easy to learn and use.
TrPC is a widely adopted library with around 25,000 stars on GitHub and a team of five active maintainers, ensuring the longevity of the project. We have found that using TrPC has a very positive effect on our development speed and facilitates our full-stack development cycle. It integrates well with React Query, which means it can be complementary to our API call stack. In addition, its integration with Edge Runtimes (such as Cloudflare Workers) allows deployment that limits infrastructure needs.
OUR POINT OF VIEW
There are still areas where TrPC lags behind other solutions, such as API versioning, internationalization, as well as a lack of support for file uploads. As a result, we decided to classify TrPC in the “assess” category as the library evolves.
HISTORY 2022
It's a new blip this year.
Managing the overall state of an app is a crucial issue to ensure its maintainability and performance. For React, various solutions have been proposed, with redux being the default choice. However, its use for global state management can quickly become complex and difficult to maintain.
The arrival of React hooks and contexts changed the game, prompting many developers to adopt them to manage the global state. React contexts offer a practical solution for sharing data to all children belonging to a branch of our component tree, regardless of their position. They thus allow us to avoid “prop drilling”. If the data changes, all the children who listen to the context come back to it again. Coupled with state hooks, we get a possible global state implementation. However, this implementation poses some problems:
performance problems related to excessive reporting, which require the implementation of preventive measures such as memorization that would be implemented by a library specialized in state management;
the state is not accessible outside the component tree, which can be useful when you want to update it following external events (e.g. receiving a push notification);
implementations become more complex more quickly due to the use of low-level APIs and the presence of boilerplate code;
debugging tools are more restricted. For example, we cannot rely on the redux devtools (compatible with other solutions like zustand) which allow us to analyze all the updates to our state and go back in time.
To avoid these problems, we recommend that you use specialized and proven libraries to manage the different types of states:
OUR POINT OF VIEW
In conclusion, we recommend the use of APIs optimized for your state management needs that will facilitate the integration of new functionalities while ensuring very good performance. Reserve the use of contexts to provide information that changes little (theme, user preferences, etc.) through the tree of your components without having to manually pass props at each level.
HISTORY 2022
It's a new blip this year.
Retrouvez l'avis de nos experts sur les techniques, plateformes, outils, langages et frameworks associés aux principales technologies mobiles que nous utilisons au quotidien chez BAM : React Native, Flutter et Native.