Facebook’s React Native is a fantastic tool. It brings the well-received React onto the mobile platforms and enables the developers to program platform agnostic mobile apps using modern tools and techniques. Today, many apps of large user base are written in React Native, such as: AirBnb, Discord, Instagram and others.
Given its wide adoption, as well as amazing ease to target both iOS and Android with a single code base, it’s an ideal choice for Calvin Payments, a solution that my co-founder and I created to help people pay their restaurant bills faster and more easily.
In practice, developing in React Native is a bittersweet experience. Here’s why:
React-native promises unified abstraction of iOS and Android, i.e. write once, run on both platform. But in practice, doing so is complicated for any non-trivial app.
For typical content driven apps that fetches data from remote APIs and display them on the screen, this might not be a problem. But if you are interacting with devices’ camera, processing payments with Apple Pay or accessing location service in the background, these tasks are not possible without interacting with native code.
Unfortunately, writing React Native libraries in native code while targeting both iOS and Android is not a simple task. Let’s take a look at some popular libraries:
Most issues are platform specific. This is not an isolated case, but a common pattern.
React-native’s community is fragmented, adoption of newer version by most users are slow. This is because upgrading is non-trivial and does not reward the effort for most people.
Till now, the best way to upgrade React Native is to use
react-native-git-upgrader. Although the tool uses git to automatically resolve a lot of merging decisions for the user, they still need to perform three-way-merging on some multiple conflicts. This process is time consuming and prone to mistakes. Newer versions of React Native may provide additional features and bug fixes but also comes at the cost of regression bugs.
As a result, unless the new features or bug fixes are fundamental, developers take a “if not broken, don’t fix it” position on keeping up to date with React Native. This increases the effort for libraries authors (often working on their own time), as they have to make sure that their library work for multiple versions of React Native .
RN is being developed at a fast pace, on average, 50 commits get pushed to the repo every week . Managing releases across multiple minor versions are hard tasks. Many users have complained about patches for blocking regressions not being cherry-picked for the patch version releases , or at least not in a timely manner. Consequently, many users are forced to apply the patches their own fork , compiling React Native from source and adding significant time to their build.
In the past, there were attempts  to crowdsource commits to be cherry-picked into stable releases. But these issues got lost very quickly into the pile of newly created issues, barely attracting enough attention. With newer releases, we are now tracking issues with minor releases in a separate repo. Hopefully, this can remedy some of issues we are facing with stable releases.
With how popular React Native has became, there will be no shortage of contribution from experience developer and newcomers trying to build their brands.
The issues I’ve mentioned above are often not entirely technical. As libraries maintainers, we can of course write more integration and end-to-end tests to cover multiple platforms across multiple React Native releases. There’s a balance that needs to be carefully maintained; keeping the quality of the projects high versus encouraging open source contributions. In the ecosystem of React Native, we are pleasing contributors way too much by merging patches that haven’t been given enough thought.
The result? a lot of platform specific bugs because contributors only code for one of iOS or Android; and majority of library consumers being reluctant to keep up to date, not wanting to spend weeks discovering hidden regression bugs.
Finally, like Jeff Geerling spoke out, ‘No’ should be default response for pull requests.