No rewrite required: How to bring Expo into mature native apps
Key Points
- Adopt Expo incrementally—no full rewrite
- Run React Native views inside existing native activities/controllers
- Some libraries need extra lifecycle setup; expo-dev-client unsupported
Summary
Skip costly rewrites by adopting Expo incrementally in mature native apps. Expo is additive: you can ship a single screen or feature in React Native while keeping your existing native codebase. This makes it practical to gain faster iteration, platform parity, and shared components without discarding previous investments.
Key Points
-
Why adopt incrementally:
- Ship a feature once to both iOS and Android for platform parity.
- Create shared JS components (design systems, charting) to reduce duplication.
- Allow product teams to build in JS while native engineers maintain platform infrastructure.
- Migrate legacy screens gradually to reduce risk and maintenance costs.
-
High-level integration steps:
- Create an Expo app inside your repo:
npx create-expo-app my-project. - Organize project root so native code lives in
ios/andandroid/(or configure a custom root). - Android: update Gradle files (settings.gradle, build.gradle, app/build.gradle, gradle.properties) for the React Native Gradle Plugin; add permissions to AndroidManifest.xml; initialize/load React Native in MainActivity; present a ReactActivity for RN views.
- iOS: add React Native pods and run
pod install; add a JS bundle build phase in Xcode; update Info.plist; create/present a ReactViewController to start the RN runtime. - Build your native app and start the Metro bundler from the RN directory:
npx expo start.
- Create an Expo app inside your repo:
-
Examples & resources:
- Reference integrations: https://github.com/expo/expo-brownfield-examples and https://github.com/gabrieldonadel/expo-brownfield-experiments.
- Full docs and unsupported libraries list: https://docs.expo.dev/brownfield/overview/.
-
Current limitations:
- Some Expo libraries require additional lifecycle listener setup on Android/iOS.
expo-dev-clientis not supported yet; more libraries will be added in future SDKs.
Practical advice
Start with a low-risk screen (onboarding, settings, chat view), keep responsibilities between native and JS clear, and use the example repositories as templates to validate integration before expanding Expo across the app.