React Native and Expo: Web and Android Development Pitfalls

Notes

This article records problems I ran into while using Expo in 2024. Expo CLI, EAS, and Android build workflows continue to change, so the commands and limitations below are not a current setup guide. Check the current EAS CLI reference and Android build documentation.

Our student innovation project needed a control panel for a remote automation system. A web and mobile version would have been useful, and I chose React Native because I was more productive in TypeScript than Dart. I used Expo to create and manage the project.

Routing and asynchronous login state

I used router.replace to move from the login screen to the main screen. It worked on the web but appeared not to work on Android.

The route had changed; the app immediately sent me back to the login screen. I stored the login state as a boolean that defaulted to false, then checked it before loading the saved value. The app therefore treated the user as logged out during startup. Waiting until the authentication state had loaded fixed the issue.

I still do not know why the timing difference showed up on Android but not in the web build.

Build workflow

Expo’s cloud build service was convenient, but in my project I had to wait in a queue, so I preferred building locally. The current EAS build options, quotas, and local-build support may differ; check the official documentation for the workflow you plan to use.

WSL

My computer ran Windows, and I chose WSL to use Linux build tools without switching operating systems. This was my choice for that setup, not a statement that Expo can only build Android apps on Linux or macOS. Cloud builds and local builds have different requirements.

I installed the EAS CLI globally with:

npm install --global eas-cli

The current Expo documentation also supports invoking it with npx eas-cli@latest. The old global expo-cli command in my original notes is not the command I recommend copying into a new project; follow the current Expo CLI documentation.

Android SDK and JDK

I installed the Android SDK using a guide for Ubuntu 20.04. The exact SDK setup has changed since then, so use the current Android and Expo documentation for a new project.

The project I was building at the time required JDK 17. I first used GraalVM 17.0.11, and Gradle failed while running jlink to create an Android JDK image for react-native-async-storage. Switching to Oracle JDK 17 through SDKMAN fixed that build for me. This is an observation about that project’s Gradle and Android Gradle Plugin versions, not a universal JDK requirement for current Expo projects.

Android package size and ABI splits

I wanted separate APKs for different Android ABIs instead of one universal package. In my setup, I could configure the native Gradle project directly, but I found the Expo path less straightforward.

EAS build profiles and native Gradle configuration can affect whether a build produces an AAB or APK and how APKs are split. See Expo’s current APK configuration guide and your project’s Gradle files before assuming a particular format is unavailable. My original result was tied to the tooling version and configuration I used in 2024.

I also disliked that my local toolchain copied project files into a temporary directory. Expo’s current CLI marks local EAS builds as experimental; check the EAS CLI reference for its present behavior.

I did not test an iOS build because I did not have an Apple Developer account.

Takeaway

The routing issue came from checking a default false value before asynchronous authentication state had loaded. The build issues reflect my 2024 machine and configuration. When using Expo today, verify current EAS and Gradle options before relying on this older troubleshooting log.