React Native: Quality and Evolution

Key Quality Attributes

React Native is a framework that builds native applications for iOS and Android using JavaScript, based on React, a JavaScript library1. React Native was created by Meta and is now an open source project, with over 2000 contributors. To ensure quality of the code React Native has a modular architecture and there are some rules and guidelines.
Before getting in detail of quality assurance let’s take a look at the key quality attributes that React Native satisfies.
In React Native one can write native module for an application directly from the iOS/Android project or as an NPM Package as dependency for other applications2. This division of application into different modules on the basis of functionality makes that React Native is a modular system.
Because React Native is such a modular system it has a high level of maintainability. One can edit in different components of the system without affecting other components.
On top of this one can easily edit one component of the development and this is a huge favour in terms of customisability.
React Native has maintained an active community on GitHub that provides feedback to each other and maintains the website. New users can learn React Native easily from the documentation and this benefits the usability of React Native. Another main benefit is that in React Native a developer has to write code once for multiple platforms. All code is written in JavaScript and in particular React, this means that the developer only has to learn this language, which makes it very accesible.

Software Quality Processes

As mentioned before React Native has an active community on that provides feedback to each others commits. Pull requests will always be reviewed by other contributors 3.
To ensure the quality of code it is important to test the code. React Native encourages developers to test their code by running yarn test and other platform-specific scripts to prevent regressions4. In the documentation there is a guideline on how to test your code, this includes tests for JavaScript, iOS, Android and end-to-end tests. Contributers are encouraged to add to these tests5. Every pull request should contain a test plan and should pass all test before it will be merged.
React Native itself also runs continuous tests like Appveyor and Circle CI. Every commit that is added to a pull request is tested with these tests to see if there is any regression5. Meta’s internal testing infrastructure also runs integration tests. These test run whenever a copy of React Native is hosted in Meta’s source control or whenever a pull request is imported in Meta’s source control.
In terms of code style there are some code guidelines in the contribution guide “How to Contribute Code” 4. React Native makes use of the formatter Prettier6. Prettier is a code formatter, which applies a consistent style by analyzing the code, considering maximal line length and wrap the code when needed7. Furthermore they use a linter to catch styling issues in code. Above this they also have some more styling guidelines for Java and Objective-C code that the above options can’t catch.

Continuous Integration Processes

As described above, React Native makes extensive use of continuous integration to garentee its code quality. The continuous integration is setup via Circle CI, self claimed fastest CI/CD platform available with 6000 free build minutes per month 8. React Native has a total of ten workflows, which are CI pipelines, setup. Three workflows only work for the main branch and the other 7 work for all branches. For the main branch there are the workflows: analysis, tests, and nightly 9. The analysis workflow contains two jobs, one for analyzing the code, called analyze_code and a job called js_coverage. They mainly conduct checks for errors, check the linting and collect the test coverage for the javascript code inside the project. The tests job performs the tests, where it tests for both iOS and Android and lastly, the nightly job which runs every night, building hermes for iOS, Linux and Windows. It also builds npm package and publishes it. With workflows of the continuous integration described above, React Native is able to enforce an adequate project and code quality. Together with Circle CI it also make keeping track of the failed, but mostly successful builds and tests extra easy.

Figure: Continuous Integration workflows for the Main branch of React Native.

Test Processes and the Role of Test Coverage

as mentioned before, React Native uses Appveyor and Circle CI to run their open source tests. These open source tests will run each time a commit is added to a pull request, to help contributors understand whether their code is passing and or changing any important inner workings 10. These tests are also applied to the master and *-stable branches to keep track of their health 10. Furthermore, there are also a couple of tests that run within Facebook’s internal test infrastructure. These tests are integration tests made by React Native developers within Facebook, forinstance part of the Facebook app. These tests also run on every commit on Facebook’s source control and they also run when a pull request is imported. If one of these tests fail, a facebook contributor has to take a look as they are the onlyones able to import pull requests. The open source tests run by Circle CI are located within the analysis and tests workflows of the analysis contains 1038 tests and the tests workflow contains 6317 tests 9. Furthermore, the test code coverage is also check within the continuous integration, however it is not clear whether there is a minimum required for the tests and files.

Hotspot Components

In this section we highlight the components within React Native that have the highest development activity11. With the tool CodeScene12 we analysed the activity from the last 12 months13 to see which files have the most commits. In total we analysed over 350 thousand lines of code spread over 2682 files. The highest number of commits was 55, with an average of 6 commits per file. In the Figure below all files are shown, ordered by the project structure.

Figure: Hotspot components from the React Native repository. Darker colours means more commits.

From this overview we filtered the top 10 of files with the most commits. These files give us a clear indication of where the hotspots from this repository are located. Eight of the ten are located in (a subfolder of) either /ReactAndroid/src/main/java/com/facebook/react or /ReactCommon/react/renderer. From the former, there are two main components to which these contributions were made: the ScrollView and Fabric; the latter concerns the Android renderer. Most of the files have seen a steady increase in commits over the years, which makes sense as they are essential components for React Native as a whole.
However, there is another reason why this outcome is not surprising: React Native is currently in the midst of a new architecture rollout that uses a new rendering renderer: Fabric14. It is therefore expected that these components will continue to receive a lot of attention during the rollout and afterwards.

Code Quality

Another functionality that is offered by CodeScene is Code Health inspection. It helps to analyse the quality of the used code, by searching for code smells and bad patterns. Some of these are

  • “A single function/method that centers too much behavior and becomes a local hotspot”;
  • “If the developer behind a hotspot with low code healt leaves the organization, the maintenance risk increases significantly”;
  • “Duplicated logic that is actually changed together in predictable patterns”,

but the documentation states that the final grade that expresses the code health is made up of 25 to 30 factors15. On the scale of 1 to 10, there are only nine files that score below a 4, meaning unhealthy. Interestingly, these files are located at the hotspots identified in the previous section. From the top-10 that was identified, there is one file that scores a 3: /ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp Simultaniously, it is also one of the larger files contained in the renderer folder with 1200 lines of code. It seems that there is a pattern here: in the folder /Libraries/Renderer/implementations there are six files that all are extremely unhealthy and long, and involve the renderer. It might be that because of the new architecture, developers have built up a technical debt, which has caused these unhealthy codes.
Outside of these mentioned files, most of the code is without big problems. In general the hotspot locations are healthy with an average of 6.95, compared to the overall average of 7.39.

Quality Culture

In React, you can use Components or you can use Functions. Where components have a state and use a render function to render React elements, functions are stateless javascript functions where you can pass props to it. It will return a React element. Since there is no state, functions are better for testing and are more modular. The React-Native community wants to have its code modular 16, so that more components can easily be integrated.
A React-Native developer commented on a pull request that it was not happy with the PR because the API was not super granular17. They prefer to have a more stable code than to implement something new that is not well integrated yet.
Since there were not many discussions in the pull requests or issues, we took the information from the community blog. In this blog, react-native states that their top priority is to match the expectations people have for each platform. They value their look and feel over cross-platform consistency 18. React-Native has started a new render architecture It now uses Fabric to render the elements 19. This new architecture makes sure that both Android and iOS have an improved performance, are more consistent and start faster. React native wants it’s app to run smoothly and to be stable, instead of having many different components. For this new architecture, they have started a working group where everyone in the group can share their ideas and discuss their opinions on this new architecture.

Assessment of Technical Debt

In React-Native there is a lot of technical debt. Most of the debt is code that converts the react code into native code. Because the android and IOs code changes, react native has to change as well, but sometimes can’t keep up with the speed. A good example is the Android permissions. For now, they have a string for the PermissionStatus and a string for the PermissionType.

Figure: Technical debt of Permissions

While actually, they want to use enums for those variables. Enums are less error-prone and helps the developer picking the right permission. But android has new permissions implemented like ‘Read phone numbers’ and ‘UWB Ranging’, so in order ot keep up with the new permissions they have used strings. Another example is the NativeAlertManager which takes care of an alert on both Android and iOS. For now, it’s argument buttons is an array of ‘Objects’.

Figure: Technical debt of buttons

This is of course too vague and needs more specification. However, to do that, you would have to implement the Android and iOS button in the code. Which takes some time and for now, this works.


  1. https://www.oreilly.com/library/view/learning-react-native/9781491929049/ch01.html ↩︎

  2. https://reactnative.dev/docs/native-modules-intro ↩︎

  3. https://github.com/facebook/react-native/wiki/Managing-Pull-Requests ↩︎

  4. https://github.com/facebook/react-native/wiki/How-to-Contribute-Code#coding-style ↩︎

  5. https://github.com/facebook/react-native/wiki/Tests#continuous-testing ↩︎

  6. https://prettier.io/ ↩︎

  7. https://github.com/prettier/prettier ↩︎

  8. https://circleci.com/ ↩︎

  9. https://app.circleci.com/insights/github/facebook/react-native?reporting-window=last-30-days ↩︎

  10. https://github.com/facebook/react-native/wiki/Tests ↩︎

  11. https://codescene.io/docs/terminology/codescene-terminology.html#hotspots ↩︎

  12. https://codescene.io/ ↩︎

  13. Date of measurement is 17th of March 2022. ↩︎

  14. https://reactnative.dev/blog/2022/03/15/an-update-on-the-new-architecture-rollout ↩︎

  15. https://codescene.io/docs/guides/technical/code-health.html ↩︎

  16. https://github.com/facebook/react-native/issues/31601 ↩︎

  17. https://github.com/facebook/react-native/pull/29466 ↩︎

  18. https://reactnative.dev/blog/2020/07/17/react-native-principles ↩︎

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