One of the apps built with our App creation technology— Nutridi

Lessons learned building multiple apps with Expo and React Native

Peadar Coyle
Level Up Coding
Published in
7 min readMay 15, 2020

--

by Peadar Coyle and Salih Kasım Benli

We used Expo managed flow for a year. Here are some things we’ve learned over the past 18 months with a small developer team.

Aflorithmic Labs (www.aflorithmic.ai) is a deep-tech focused startup that’s building a platform for brands to create personalized audio experiences. Our clients and users often look for apps as a delivery mechanism so we’ve built some tooling to make it easy to create apps, connecting to our APIs in the backend.

When we were starting our journey about 18 months ago, our founder Peadar evaluated React-Native, native code, and flutter.

Our core philosophy when building apps is that we look to abstract what we can to our backend APIs and we look to streamline the app generation process as much as possible.

Our mobile app tech stack

*We’ve benefited from all the work the amazing Expo team has done on the ecosystem, but since we started over a year ago (notably, before Expo launched web support) and because we have a number of native components — in particular audio-focused, we’re on what’s essentially the Bare workflow.

History

We picked React-Native because it felt the most well-established community at the time, and we wanted the advantage of one shared code base across both iOS and Android. In particular, we picked Expo an SDK on top of react-native which made the development process even more seamless. We eventually ejected from Expo to the bare workflow. However the first 1 year of our development, of apps such as www.withhislight.app (an app built using our personalized audio API)

Philosophy

All applications should have a philosophy behind them.

For us, we had a few guiding principles in terms of user experience and the tooling we picked.

  • Should work on both platforms (Android and iOS)
  • We should try to keep as much code overlapping as possible — although we do have some platform-specific code in the codebase.
  • If we can buy in a third party service we should — hence we picked AWS Amplify for our authentication and earlier analytics, and other tooling such as AWS Lambdas.
  • We tried to keep the front-end as agnostic as possible, so where possible we put stuff into our APIs. This informed a lot of our code decisions.
  • We wanted a world-class UX. And our software engineers spent a lot of time streamlining our UX experience. We’re still not where we want to be but we’re pretty proud of our experience.
  • Velocity, since we were still trying to figure out product-market fit we wanted to make deployment of new features as smooth as possible.
Some screenshots of one of our apps on the IPad. Expo made it easy to be cross-platform.

React-native also allows you to share some knowledge with React.js so while there are differences between web and mobile apps, often it’s quite easy for someone with a rudimentary knowledge of react.js to pick up native. To pick up Java and Objective C is much harder.

In fact, one of our founders still doesn’t know much javascript and he was able to code the MVP from scratch. He came from a python background, so if he can build an app any developer can!

Let’s delve into some of the trade-offs about Expo and React Native components. These are audio player focused, but even if your app is a different app, you may get something out of this.

Expo Audio Player

Expo AV, expo’s audio and video player, is designed to just work. You can spin up an audio or video app in less than 2 weeks. Since it’s built by the Expo team, it’s built to be easy-to-use and opinionated. Opinionated means that there’s only one way to do certain things (so the API is somewhat restrictive), so this accelerates product development. However, opinionated also means that eventually, we reached some problems with it. The Expo team is fast at developing, so sometimes we could wait for an SDK upgrade — for example at one point it didn’t allow playing audio in the background, this was resolved in an SDK upgrade.

What are some of the disadvantages — it does not feel native. It does not have lock screen and notifications controls, does not have a stable background mode, stops when changing tracks on iOS. Despite this, for an MVP it works pretty well.

We noticed that when we moved to “react-native-track-player” is that it is not working app-wide. This means that it stops when the component having it unmounts, it also has some problems with global state, increasing the music-related screen’s codebase due to the fact that we have to foster that sound related logic there. Since all of the logic is built around a “playbackObject”, it is impossible to reach audio related data outside that component. After using “react-native-track-player”, we implemented a “useTrackPlayer” custom hook that can be used anywhere in the app to obtain percentage, duration left, state and more.

Expo AV is designed to just “work” as mentioned before, so if one wants to have a sound-centered app, like a podcast or radio app, it will not meet the requirements after a certain point. However, it is versatile, Expo AV also supports playing videos. Hence, for an MVP, it is recommended to go with it. However, to get an improved UX like Spotify, native modules are better. The learning for this is that to go fast, you need to give up some control. This is the power of frameworks.

Push Notifications

Push notifications are another topic Expo helps a lot when creating an MVP. It is easy to use and test, dealing with certificates and credentials is left to Expo servers and with a simple backend, it may just work.

Even though this is really helpful at the very beginning of the development, as the product evolves to something there will be a need to use a more complicated and powerful service. OneSignal, react-native-push-notification and wix/react-native-notifications are examples of those services/packages. Additionally, if Expo’s notification servers are used, any other tool can not be used. For example, you can not combine Expo’s way of handling push notifications with MixPanel. Expo team is making a great job on documentation and supporting the community, there are a lot of examples to design a backend talking to Expo’s servers to send notifications, see https://docs.expo.io/guides/push-notifications/#2-call-expos-push-api-with-the for further details.

Using native modules

While developing a react native app, it may be needed to use native modules. A native module can be briefly explained as a package that uses native code to accomplish some sort of tasks and communicates with react native. They are usually written in Java, Obj-C or Swift. If Expo is used, no native packages can be used (except the ones Expo team has already made available) So, this is why “react-native-track-player”, “react-native-iap” or “react-native-wheel-picker-android“ and many other great packages can not be used with Expo. However, Expo team always tries to come up with a solution to common issues, e.g https://docs.expo.io/versions/latest/sdk/in-app-purchases/

Expo CLI — https://github.com/expo/expo-cli

I have been using expo-cli for 2 years as of today. It has changed so much and got better. “expo install” or “expo upgrade” are examples of this solid improvement. In addition, this awesome cli is really useful to automate releases and tests. A CI/CD system can be built easily and fast by using expo-cli.

Bare Workflow

Expo gives developers an option to eject. Ejecting means going to “bare workflow” from “managed workflow”. More details can be found on their website. As aflorithmic Labs, we eventually picked this option after 1 year of development, in particular, there were some native-modules we wanted to use. Ejecting isn’t free. So it’s worth pointing this out. After ejecting there were some problems encountered:

  • CI/CD setup needs to be renewed — in particular we lost one week to gradle build errors
  • Managing certificates/credentials gets harder
  • Native module setup can be harder than just running “expo install”
  • The configuration is a lot harder. Instead of just changing app.json, a lot of native directories and files should be edited.

Final thoughts

Expo is a really great package, developed by a great team and one of the best communities. All of the react-native projects that can be tested without touching a device if written on Snack, which is also developed by the Expo team. However, as everywhere in life, it has some shortcomings, which we mentioned above.

If one is a new startup, trying to convince a customer or decided to create a new product about some new topic, then he should use Expo by default (if there is no limitation known). We (Aflorithmic Labs), used Expo for 1 year to have an audio app in production and available on App Store and Play Store.

Thus, one should not think of Expo as a package to just start. There might really be no reason not to use it.

In any side projects we build, we immediately turn to Expo and existing toolkits such as Firebase and Amplify. This significantly reduces the time to build and deploy an app, and while we were skeptical at first. We were amazed by how far we got with Expo alone. Thanks for all the great work to the Expo team.

If you want to try out some apps built with our platform you can look at WithHisLight which is available on iPhone and on Google Play

--

--