Mobile App Migration from React Native to Flutter
Migration from React Native to Flutter — not a screen-by-screen port. This is rethinking architecture: different language (Dart instead of JavaScript/TypeScript), different rendering model (Skia/Impeller instead of native components), different state management patterns. Project with 50 screens with Redux and react-navigation doesn't become Flutter app in two weeks.
We do such migrations gradually or with full rewrite — depends on project size and criticality of continuous operation.
Why this is harder than it seems
No direct component analogs. In React Native FlatList with keyExtractor, renderItem and getItemLayout — familiar construct. In Flutter ListView.builder works similarly, but SliverList with SliverChildBuilderDelegate — completely different level. Developers coming from RN often use Column + SingleChildScrollView where CustomScrollView with Slivers is needed — and get jank on long lists.
Navigation. In React Native navigation ecosystem lives in react-navigation with familiar Stack, Tab, Drawer concepts. In Flutter official path — Navigator 2.0 with Router and RouteInformationParser, conceptually harder. In practice we migrate to go_router (recommended by Flutter team): gives declarative navigation with deep linking and typed parameters. Porting navigation structure — separate task, can't automate.
Native modules. In React Native custom native modules written in Java/Kotlin and Objective-C/Swift via bridge. In Flutter — Platform Channels: MethodChannel, EventChannel, BasicMessageChannel. Semantics same, implementation different. If RN project has custom modules (Bluetooth, NFC, specific hardware), must rewrite for Flutter Platform Channels or find Flutter plugin in pub.dev.
State management. Redux → Bloc/Cubit — conceptually close (unidirectional flow, actions/events, reducers/states). No automatic code conversion though. MobX → Riverpod or Provider — harder, because MobX reactive model has no direct analog. Riverpod 2.x with @riverpod annotations — good choice for teams valuing compile-time safety.
How we conduct migration
Audit and inventory. First step — complete project map: screen list, native dependencies, third-party SDKs (analytics, payments, maps), custom native modules. For each RN dependency find Flutter analog or determine if need to write Plugin independently.
| React Native | Flutter equivalent |
|---|---|
| react-navigation | go_router |
| redux / redux-toolkit | bloc / cubit |
| react-query | riverpod + dio |
| react-native-mmkv | shared_preferences / hive |
| react-native-reanimated | flutter_animate / rive |
| react-native-maps | google_maps_flutter |
| react-native-camera | camera / image_picker |
| react-native-purchase | purchases_flutter (RevenueCat) |
Phased migration strategy. For large projects (30+ screens) use Add-to-App approach: Flutter module embedded in existing RN app via FlutterEngine. Screens migrate one by one until entire project is on Flutter. This gives opportunity to test each migrated module in production before full switch.
For small projects (under 20 screens) — full rewrite faster and cleaner. Parallel new Flutter app development with gradual QA.
Dart and typing. TypeScript developers adapt to Dart quickly: static typing, null safety (since Dart 2.12), async/await, generics — all familiar. Surprising feature: in Dart no interface keyword, any class can be implemented. And required named parameters — standard practice for readable widgets.
Testing. Flutter provides three levels: unit tests (flutter_test), widget tests (render widgets without device), integration tests (integration_test package, runs on real device or simulator). Transfer critical business logic test coverage along with code — insurance during migration.
What impacts timelines
Linear dependency on screen count works only for simple CRUD forms. Real multipliers:
- custom native modules — +2–5 days each
- complex animation (react-native-reanimated → rive/flutter_animate) — +1–3 days per screen
- payment integrations (In-App Purchase, Stripe) — +3–7 days
- maps with custom markers and geolocation — +4–8 days
- CI/CD setup for Flutter (Fastlane, GitHub Actions) — +2–3 days
Typical project with 20–30 screens without complex native logic: 6–12 weeks. Cost calculated after auditing code base and compiling complete dependency list.







