From web to native with React Native and Expo

Users14 minutes read

Yung Chomsky

Yung Chomsky

Guest Author

What's it like for a web dev to build a mobile app for the first time? Learn from the trials, tribulations, and victories of Yung Chomsky and his phomo app.

phomo-app

This is a guest post from Yung Chomsky - a software developer and podcast producer based in Brooklyn, New York. He is the developer of phomo - a media library application.

•••

Last summer, I had an idea for a mobile app.

It began with a desire to improve an existing workflow: Each day after I get dressed, I like to take a photo of my outfit for the day. After I take the photo, I add it to an album on my phone. Simple enough, but the process seemed to take more taps than necessary using the default iOS Camera and Photos apps. Plus, I wanted to see the photos laid out by date, to filter and group them, to view trends and stats about them. So I started thinking about what my preferred UX would look like, and what it might take to implement.

I’m an experienced programmer — I spent 7 years as a software engineer at companies small and large. But I had only ever worked on web apps. This seemed like the perfect opportunity to try my hand at a mobile app. Fortunately, React Native and Expo were there to make things a lot easier for me.

What is phomo?

I first published the app earlier this year, and have pushed out a bunch of updates since. It’s called phomo, and it’s grown beyond its original concept into a full-fledged media library and camera. It’s in the iOS app store now, with an Android version on the way. phomo lets you capture high-quality photos and save them directly to albums, search your photos with custom user- or machine-generated tags, see interactive charts with usage stats, and create shareable photo grids and slideshows. It’s totally free, and it looks like this:

I learned a lot building phomo, and encountered a few surprises — some things were easier than I anticipated, others more difficult. I’m going to talk a little about the pleasant surprises and the challenges in the hopes that I can help some other native-curious web developers out there.

Web to native: The easy parts

Back when I was first messing around with web sites as a teenager, a simple view source or inspect element would show you everything you needed to know about how a site was made. Web development has gotten a lot more complex since then, but modern tools can still provide a quick and frictionless developer experience.

This didn’t seem to be the case with React Native when I first checked it out, back in 2015. That’s changed significantly thanks to Expo, a suite of open-source tools for React Native (the team at Meta recently recommended Expo as their preferred framework for building React Native apps).

Getting started with Expo

At a high level, Expo is a way to abstract away many of the more painful aspects of the native developer experience, particularly the process of compiling the native binary and publishing to the app stores. I’d never heard of Expo before I started working on phomo, and I certainly didn’t have a full understanding of the ecosystem when I decided to dive in, so I’ll give the quick overview I wish I had been given.

Expo Go is a native sandbox app that provides a pre-built native environment for your app’s JavaScript to run on top of. It also gives you access to the Expo SDK, a collection of libraries which allow you to interface with native APIs for things like the camera, file system, GPS, etc. Developing with Expo Go is essentially as smooth as working with React on the web, and I was able to get up and running quickly and accomplish a lot using this setup. My production app uses a bunch of libraries from the Expo SDK. The one I lean on the most is expo-media-library. The documentation is great, and it’s super straightforward to request permissions, load or create albums, save images, and so on.

Building with Expo

Eventually though, you’ll want to access some native features or libraries that aren’t bundled into Expo Go. In earlier versions, this would’ve meant leaving Expo behind by “ejecting,” but this is no longer the case (and hasn’t been for years). At this point you just have to generate a new, custom version of Expo Go, also known as an Expo development client, and then you can carry on with the same workflow as before.

This chart depicts a few of the libraries, both Expo and non-, that phomo relies on for various features:

I was at first a little intimidated by the build process, but Expo provides a CLI that makes it easy. By default your builds run on Expo’s servers, which is free up to a point, but you can also build on your own machine for free by using the —local flag. Then when you want to submit to app stores, that’s also simple to do with the CLI. All native app submissions have to go through a review process before they appear in the app stores, whether it’s the first build or a new version.

Submitting and updating with Expo

I was a bit surprised by the strictness of Apple’s review process — I think I had to resubmit phomo 5 times before it was first accepted. The requested changes weren’t large or difficult to make — several of them involved minor text changes around the UI for requesting permissions — but each round can take a day or more. Suffice to say that Apple requires precise adherence to the letter of their guidelines.

Another Expo tool comes in handy here: EAS Update. Any changes to the native code of an app will require a new build, and therefore a new app store submission and a new review. But if you’ve only made JavaScript changes, with EAS Update you can push out an over-the-air (OTA) update, which means you can deliver bug fixes quickly without having to wait for another review. Also worth mentioning is EAS insights, a (currently in public preview and thus free-to-use) web dashboard showing how many active users your app has, broken out by platform and version; and Expo push notifications, which provides cross-platform client and server tools to easily send notifications.

Styling a mobile app

Lastly, I want to touch on styling, as it seems to be a common concern for new React Native developers. I’ve seen a lot of questions in various RN communities about third-party UI libraries, as though using one is de rigueur. I think such off-the-shelf libraries certainly have use cases, but I don’t think they’re any more necessary for native apps than they are on the web. React Native’s StyleSheet API is just CSS with a few differences; anyone familiar with CSS, and especially CSS-in-JS, should have no trouble writing their own styles. When I first started working on phomo I installed a UI component library, but over time I’ve almost entirely removed it in favor of writing my own styles, which offers better performance and more flexibility.

Web to native: The hard parts

Those were a few of the things that pleasantly surprised me; now let’s get to the less pleasant parts.

Debugging a mobile app

If you’re anything like me, a lot of your time is spent on debugging. I’m proficient with Chrome’s developer tools — finding elements; using breakpoints; profiling performance, etc. There are various ways to do all of these things in a React Native app, but none of them are as convenient or flexible as I’m used to. The debugging experience has gotten better in the latest version of Expo as compared to the previous one, though, and I believe it will continue to improve.

The pain of performance optimization

Performance optimization is another area I spent more time on that I’d anticipated. In the React world, I see more warnings against “premature optimization” than I do against inefficient code. This is an understandable reaction to the common tendency to overuse React’s useCallback, useMemo, etc. And in a standard CRUD app, optimization might often be premature. However, I found optimization to be essential when it came to things like rendering the user’s entire media library in a scrollable list. The animated bells and whistles that mobile users are used to, as well as the inherent nature of a touch interface, make less-than-smooth performance in a mobile app very apparent. Understanding how to use the JS and UI threads was important for implementing smooth gestures and animations; in the end though, most of my optimizing simply involved avoiding unnecessary computations, just like in any other language or framework.

The real key was measuring performance to see what needed to be optimized in the first place. For a while, I had naively assumed that expo-media-library or React Native itself were causing my app to stutter; only after measuring with performance.now calls along with the React DevTools profiler was I able to determine that it was actually my code, and home in on what needed to be improved.

Unstable solutions and camera challenges

I was surprised a few times to learn that certain features simply don’t have canonical, stable solutions yet. I wasn’t familiar with the term for “shared element transitions,” but it was something I’d seen before and wanted to implement. When I tried, though, I learned that it’s still considered an experimental feature in React Native. I managed to implement it, but only in a limited way, using a different library which is no longer maintained. The camera is another area I was naive about: My expectation was that all the features of the stock iOS camera would be easily accessible via JavaScript, but that’s not quite the case. The expo-camera library, while simple to use, provides access to only a small subset of hardware functions. I ended up using react-native-vision-camera, which is very powerful, but its API is still in flux — it’s gone through two major version bumps in the time I’ve been working on phomo.

Building for Android vs iOS

Finally, you may have noticed that phomo is available for iOS, but not Android. I’m currently working on the Android version, but I decided to focus on iOS first, since I’m more familiar with that platform. But, you might ask, isn’t the whole point of React Native to abstract away the differences between iOS and Android, so you can “learn once, write anywhere?” Well, yes, but there are caveats. Some things just work differently on the two platforms — for instance, the way the two platforms handle permissions, or photo albums. Other libraries or features, like the BlurView, function differently on each platform. React Native and Expo smooth out a lot of cross-platform differences, but you may still have to handle some yourself, in addition to testing thoroughly in each environment.

What web devs should expect from mobile development

There’s lots more I could say about this experience, but the bottom line is this: I was able to start building right away using my existing skills, and I managed to create a mobile app that people are using.

Writing software would be boring if it weren’t challenging. But challenges are typically only rewarding when the conditions are right; a challenge that we aren’t equipped to take on will simply be frustrating. However, when we have the knowledge and skills to grapple with a challenge successfully, we emerge with more knowledge, better skills, and a sense of accomplishment. A web developer’s first React Native app falls into that latter category: You’ll know enough to get started right away, and while there will likely be obstacles, your background will give you the requisite skills to clear them.

My general advice is: always read the docs! The documentation for React, React Native, and Expo is so thorough that it can seem overwhelming, but take your time and revisit it often as you build. Many of your questions will be answered there. When the docs don’t suffice, there are multiple active communities on places like reddit and Discord full of helpful folks. And as always with open-source software, don’t forget to search (and contribute to) the GitHub issues if you run into trouble with a library.

As for me, my next goal is to get the Android version of phomo ready for prime time. Then I’ve got lots more features planned — there are a bunch of libraries and APIs I want to experiment with, like Skia, and I’m tempted to try my hand at writing native modules as well. I’m also planning to write a series of articles about how I solved specific technical challenges in the app. I’ve already published the first installment, which explains the implementation of the calendar image gallery (complete with working demo via Snack, another super-handy tool provided by Expo).

So if you’re a web dev with an idea for a native app, but you’re uncertain about whether you can hack it, I say: Jump in! The water’s fine.


web dev to mobile
expo go
expo-media-library
EAS Update

Dive in, and create your first Expo project

Learn more