React Native and Expo – A good choice for developing cross-platform apps

February 3, 2020 6 min. read

At 3angleTech, we do not shy away from trying new platforms when we develop the products that our customers need. We have experience with native apps, but we are also open to using new platforms. This helps us remain relevant, both as individual software developers and as a company. One day, a customer wanted us to develop a subscription-based podcast-like mobile app that could help users learn a foreign language. The plan was to use it to deliver original audio content that was a mix between entertainment and education, in multiple languages, to an international audience. One possible approach was to develop two separate native apps for Android and iOS, with the same features. However, for this project, more than for others, we were constrained by time, money, and maintenance costs. That’s why we decided to try a different approach and dip our toes into React Native. Here’s how it went and what we learned from it.

Developing an MVP (Minimum Viable Product) as quickly as possible. Is React Native a good choice?

Our goal was to develop a Minimum Viable Product (MVP) as fast as possible, with a minimum of work, so that we could test our customer’s ideas. We did not want to invest into developing native apps for both Android and iOS, because it would have meant doing the same work twice and having to solve the different bugs and issues specific to each mobile platform. We wanted to use a platform that offers support for one codebase to build the app for both Android and iOS. We analyzed the following options:

  • Xamarin – an open-source platform for building Android and iOS apps with .NET and C#. It is one of the oldest options for building cross-platform apps. Unfortunately, we had to exclude it because it has few open source libraries, the cost of development tools is higher than for other platforms, and the development community is small.
  • Ionic – an open-source mobile user interface toolkit for developing cross-platform apps for native iOS, Android, and the web — all from a single codebase. It works with React components, which is a plus for us, but it has no native widgets, so we decided to skip it.
  • Flutter – is Google’s user interface toolkit for natively compiled applications for mobile, web, and desktop, using a single codebase. It looked promising, but we considered it to be in its early stages of development and not mature enough for our needs. Therefore, we decided to exclude it.
  • React Native – Facebook’s framework for building native cross-platform mobile apps using JavaScript. We liked that React Native uses the same fundamental user interface building blocks as regular iOS and Android apps. You just put those building blocks together using JavaScript and React. It also features native Android/iOS widgets, so it made a good fit.

We decided to use React Native because we could also enroll our web developers on this project and provide an app with a “close to native” mobile experience. The promise of React Native seemed very exciting and exactly what we needed for this project.

Developing the MVP with Expo and React Native

We started our work by studying the documentation for React Native, and we were thrilled to find useful step-by-step guides and explanations in it. The “Getting Started” section led us to the Expo software development kit. We immediately installed the Expo app from the Play Store and the App Store, so that we could use it during the development process. At this point, we weren’t exactly sure how it would be used, but we knew we would figure it out. 🙂

We wrote our Hello World code, and wanted to build it, so that we could see it run. But hey, the documentation told us to scan a QR code from the terminal, with Expo, and the project will run?!? What kind of sorcery is this? It’s nice, in a weird way, but it doesn’t feel like software engineering. Scanning QR codes, really?

 

We found out later that, in Expo, there is also a build option available from the console. Still, the documentation did not promote it, probably to make things friendlier for beginners.

We decided to adapt and continue with our work. We started the development process, and figured out what libraries and components we needed. During this process, we learned that ExpoKit is the library that provides support for the native functionality we required: audio playback support, storage, native widgets, notifications, etc.

We arrived at the point when we wanted to build the app and share it with others by publishing it somewhere. We noticed that the package size was huge for a couple of static pages (around 20 MB), which is a lot for a mobile app in an MVP stage. We decided to ignore that for the moment and created a task in our product backlog for minifying the size of those pages.

Hitting a dead-end with Expo

After using Expo to develop some features for the client’s app, we hit a dead-end. Expo did not support some of the features we needed, like background audio playback or Firebase Cloud Messaging to notify users about new podcasts in our app, even when they have the app closed. It seems that not all native APIs are supported in Expo. For example, at the time this article was written, some features were still missing, like Bluetooth support, WebRTC support, and more.

Unfortunately, on the Getting Started page for React Native, there was a barely-visible link to the Limitations of Expo, which listed the reasons why Expo wasn’t the right choice for our MVP. What a bummer! We had all this code intensely coupled to a software development kit that couldn’t deliver what we needed.

Rolling back to a clean React Native app

We had to find another way, so we first tried to decouple from Expo using the expo eject command. It promised to transform the project into what we wanted: only React Native modules, without Expo. Unfortunately, it did not work well, so we ended up bootstrapping again: this time a clean React Native app, without using Expo. We replaced all the Expo modules with React Native modules, and, while doing that, the software development workflow seemed familiar again: we built the app using commands, Gradle, Xcode, and other familiar tools. We were done being “wizards” who scan QR codes. 🙂

To make things better, the build size was considerably smaller (5 MB vs. 20 MB with Expo), we had better app startup times and improved performance. It seemed too good to be true.

React Native and the packages horror story

And it was… too good to be true. To finish the app, we had to explore GitHub for libraries that offer basic features, which are omnipresent in other platforms: background audio playback, push notifications, store purchases, subscriptions, etc. We became frustrated, arriving at one bitter conclusion: except for those backed by Facebook, React Native has few quality libraries developed by third parties. Most of them are incomplete, buggy, filled with lots of hacky, immature code, abandoned, or undocumented.

To make things worse, React Native version upgrades broke up dependencies like no other platform we worked with. A small upgrade, like going from version 0.58 to 0.59, made our app builds fail. We always had to improvise new fixes to have a successful build, with no clear understanding of why things break so often with React Native.

Pros and Cons: Are Expo and React Native worth using?

When we finished the MVP for our customer, we did measure fewer software development hours than when we built two native apps. However, the experience was awful, stressful, and tiring for our developers. We ended up in situations where we had difficulty estimating the time required to develop a particular feature. It was risky to promise our customer that we can deliver a feature he requested, because of the bumpy and unpredictable nature of our development experience with React Native. So yes, we did enjoy some benefits, such as using JavaScript to develop a cross-platform mobile app, native widgets, and the fact that the app reloaded itself when the code was modified, without having to rebuild it. However, the immature ecosystem and the misleading documentation made our lives more complicated than they would have been with other ecosystems.

Do we recommend Expo and React Native?

After this adventure, we recommend that other software development teams cautiously adopt Expo and React Native, depending on their needs. First of all, you should educate yourself about the limitations of both. When you develop apps using React Native, it is a good idea to stick to the core components and APIs that are developed by Facebook, and not those created by third parties. Going this route may be a great idea when developing mobile apps that do not require many native integrations, for the following reasons:

  • Lower costs
  • Velocity
  • You do not need specialized Android/iOS developers, making it easier to find the people required to work on your project
  • The codebase is easier to maintain

However, if many native integrations are required, and they are part of the app’s core functionality, native apps may be the better approach, as they help you plan, estimate, and deliver more reliably. And we all know how precious reliability and predictability are for our customers.

This was our experience with Expo and React Native. If you found this story useful and feel that it is worth sharing with other software developers and tech companies, do not hesitate to tweet it, post it on LinkedIn, or Facebook.