Why I Ditched Expo for Bare React Native

Why I Ditched Expo for Bare React Native

I wanted to try using React Native to develop mobile apps because I didn’t want to manage two codebases (Kotlin and Swift). I dabbled with Ionic a little bit, but it’s not the ideal solution (I’ll write an article about that one day).

Anyway, I jumped right in without doing much research (my first mistake) and started working on redoing one of my old apps. I installed all the required files, dependencies, etc., to get React Native working. There was this thing called Expo Go that lets you load and test your app immediately after making changes. That seemed pretty cool; no need to mess with emulators, no need to compile anything, just scan a QR code and test your app instantly.

I almost completely recreated and beautified my old app and was ready to implement the last feature. I thought the progress was great… until I had to start using native features.

The Ejection Nightmare

Apparently, if you want to use anything Expo doesn’t support like background services, third-party native modules, or lower-level optimizations; you have to eject. Ejecting essentially converts your Expo project into a full-fledged React Native app, meaning you now have separate iOS and Android projects that you compile using Xcode and Android Studio.

And once you eject? There’s no going back. You lose the whole Expo Go setup and have to start dealing with platform-specific configuration, dependency hell, and debugging issues that didn’t exist before. At this point, Expo started to feel like developing an app with extra steps… first, you build in a nice, streamlined Expo environment, and then, when you need real functionality, you’re forced to rebuild everything again in bare React Native.

Converting an Expo App to Bare React Native is a Mess

So, I figured: why not just cut out the middleman and use bare React Native from the start?

That was another adventure. Converting an existing Expo app to bare React Native is not a smooth process. Half the dependencies break, you run into issues with native modules that weren’t properly linked, and suddenly, you’re scrolling through Stack Overflow threads from 2019 trying to figure out why Xcode won’t recognize your app.

To make things worse, React Native requires different configurations for iOS and Android, so even after fixing one issue, I had to repeat the whole process for the other platform. Biggest nightmare of all time.

Conclusion: Just Use Bare React Native

At this point, I realized Expo is great for prototyping, but if you’re serious about building a real-world app, you’re going to hit a wall. Switching to bare React Native might be more work at the beginning, but at least I won’t have to deal with Expo’s limitations or suddenly restructure my entire project later.

So now I’m just rebuilding my app using bare React Native. I’ll tell you how horribly that goes in a week.