Migrating from Xamarin or PhoneGap to React Native: When It's the Right Move
React Native is the right migration target when you want a broader ecosystem, stronger community support, or when the existing app is Xamarin.Native or PhoneGap (where MAUI is not a viable option). The migration involves a language change, but the business logic is preservable and the result is a more maintainable, more hireable, better-supported mobile stack.
- React Native with Expo is our recommended default for new enterprise mobile projects and migrations.
- Business logic (API clients, data models, validation) can be translated from C# or JavaScript to TypeScript with AI assistance.
- The UI layer is a rebuild, not a translation, because the rendering models are fundamentally different.
- Expo simplifies the build, deployment, and update lifecycle significantly compared to both Xamarin and PhoneGap.
- Budget 6-12 weeks for a mid-complexity app, depending on screen count and native integration complexity.
When React Native is the right target
This guide is for teams that have decided (or are deciding) that React Native is the right migration target. If you are still choosing between MAUI and React Native, read our comparison guide first.
React Native is the right choice for:
PhoneGap and Cordova apps. There is no direct migration path from PhoneGap to MAUI. React Native is the natural successor: it runs native components (not a WebView), has a mature plugin ecosystem, and uses JavaScript/TypeScript (which PhoneGap developers already know).
Xamarin.Native apps (Xamarin.iOS / Xamarin.Android). These apps used platform-specific APIs directly, without the Xamarin.Forms abstraction layer. Migrating to MAUI offers no structural advantage because MAUI is the successor to Xamarin.Forms, not Xamarin.Native. The migration effort to either MAUI or React Native is comparable, so choose based on ecosystem and hiring factors.
Teams investing in web and mobile. If your organisation also builds web applications in React, sharing code and knowledge between web and mobile teams is a practical benefit. Component patterns, state management approaches, and TypeScript skills transfer directly.
Hiring-constrained teams. The React/React Native developer market is significantly larger than the MAUI developer market. If recruiting speed matters, React Native has an advantage.
Architecture mapping: where your code lands
Understanding how the old architecture maps to React Native helps plan the migration.
From Xamarin
| Xamarin concept | React Native equivalent |
|---|---|
| ViewModel (MVVM) | Custom Hook or Context Provider |
| ContentPage (XAML) | Screen Component (JSX/TSX) |
| NavigationPage / Shell | React Navigation (Stack, Tab, Drawer) |
| DependencyService | React Context or module imports |
| MessagingCenter | Event emitters, Zustand, or React Query |
| Xamarin.Essentials | expo-* packages (camera, location, etc.) |
| Custom Renderer | Native Module or Expo Module |
| Data binding (XAML) | Props, state, and React hooks |
From PhoneGap/Cordova
| PhoneGap concept | React Native equivalent |
|---|---|
| HTML page | Screen Component (JSX/TSX) |
| CSS styling | StyleSheet or NativeWind |
| Cordova plugin | Expo module or React Native library |
cordova.exec() | Native Module bridge (TurboModule) |
| WebView rendering | Native component rendering |
deviceready event | useEffect hook in root component |
| LocalStorage | AsyncStorage or expo-secure-store |
| Ajax/fetch | fetch API (same, but typed with TypeScript) |
Project setup with Expo
We recommend Expo for all new React Native projects. The historical trade-off (Expo was simpler but limited) no longer applies. Expo’s development builds support custom native modules, and EAS Build handles the iOS and Android build pipelines.
npx create-expo-app MyApp --template expo-template-blank-typescript
cd MyApp
Project structure
MyApp/
├── app/ # Screens (using Expo Router)
│ ├── (tabs)/ # Tab-based navigation group
│ │ ├── index.tsx # Home screen
│ │ ├── orders.tsx # Orders screen
│ │ └── profile.tsx # Profile screen
│ ├── order/
│ │ └── [id].tsx # Order detail (dynamic route)
│ └── _layout.tsx # Root layout
├── components/ # Shared UI components
├── hooks/ # Custom hooks (business logic)
├── services/ # API clients and external integrations
├── models/ # TypeScript types and interfaces
├── stores/ # State management (Zustand)
└── utils/ # Pure utility functions
Expo Router provides file-based routing similar to Next.js. This is a significant improvement over both Xamarin’s navigation stack and PhoneGap’s URL-based routing.
Migrating business logic
Business logic is the most preservable layer in any migration. API clients, data transformation functions, validation rules, and domain models can be translated to TypeScript.
C# to TypeScript (from Xamarin)
// BEFORE: Xamarin C# model and service
public class Order
{
public int Id { get; set; }
public string CustomerName { get; set; }
public DateTime OrderDate { get; set; }
public List<OrderLine> Lines { get; set; }
public decimal Total => Lines?.Sum(l => l.Quantity * l.UnitPrice) ?? 0;
}
public class OrderService
{
private readonly HttpClient _client;
public async Task<List<Order>> GetOrdersAsync(int customerId)
{
var response = await _client.GetAsync(
$"api/orders?customerId={customerId}");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<Order>>(json);
}
}
// AFTER: React Native TypeScript (generated by Claude Code)
interface OrderLine {
quantity: number;
unitPrice: number;
}
interface Order {
id: number;
customerName: string;
orderDate: string;
lines: OrderLine[];
}
function calculateTotal(order: Order): number {
return order.lines.reduce(
(sum, line) => sum + line.quantity * line.unitPrice,
0
);
}
async function getOrders(customerId: number): Promise<Order[]> {
const response = await fetch(
`${API_BASE_URL}/api/orders?customerId=${customerId}`
);
if (!response.ok) {
throw new Error(`Failed to fetch orders: ${response.status}`);
}
return response.json();
}
Claude Code handles this translation accurately for data models, API clients, and utility functions. The type mapping (C# decimal to TypeScript number, C# DateTime to TypeScript string for JSON, C# List<T> to TypeScript T[]) is well-defined.
JavaScript to TypeScript (from PhoneGap)
PhoneGap apps written in JavaScript benefit significantly from TypeScript migration. Claude Code adds types to untyped JavaScript, catches potential null reference issues, and structures the code into typed modules.
// BEFORE: PhoneGap JavaScript
function getOrders(customerId, callback) {
$.ajax({
url: API_URL + '/api/orders?customerId=' + customerId,
method: 'GET',
success: function(data) { callback(null, data); },
error: function(err) { callback(err, null); }
});
}
// AFTER: React Native TypeScript with React Query
import { useQuery } from '@tanstack/react-query';
function useOrders(customerId: number) {
return useQuery({
queryKey: ['orders', customerId],
queryFn: async () => {
const response = await fetch(
`${API_BASE_URL}/api/orders?customerId=${customerId}`
);
if (!response.ok) throw new Error('Failed to fetch orders');
return response.json() as Promise<Order[]>;
},
});
}
The pattern shift from callback-based jQuery to React Query hooks is significant but well-suited to AI-assisted translation. Claude Code understands both paradigms and generates idiomatic React Native code.
Migrating the UI layer
The UI layer is where the migration shifts from translation to rebuild. Neither Xamarin XAML nor PhoneGap HTML maps directly to React Native JSX.
Approach: screen-by-screen rebuild
Rather than attempting to translate UI markup mechanically, we approach the UI migration as a screen-by-screen rebuild using the existing app as a visual specification:
- Screenshot every screen in the existing app (both platforms)
- Build a component library of shared UI primitives (buttons, inputs, cards, lists)
- Rebuild each screen using the component library, matching the existing design
- Review on devices for visual parity
AI tooling helps here by generating component scaffolding from screen descriptions and by producing styled components that match the existing design system. But the visual fidelity check is a human activity.
Styling
React Native does not use CSS. It uses a subset of CSS properties expressed as JavaScript objects:
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
backgroundColor: '#ffffff',
},
title: {
fontSize: 24,
fontWeight: '600',
marginBottom: 8,
},
});
For teams that prefer a CSS-like workflow, NativeWind (Tailwind CSS for React Native) provides utility classes:
<View className="flex-1 p-4 bg-white">
<Text className="text-2xl font-semibold mb-2">Order Details</Text>
</View>
Plugin migration
Both Xamarin and PhoneGap relied heavily on plugins for device features. React Native’s ecosystem provides equivalents for virtually all common plugins.
Recommended Expo packages
| Capability | Expo Package | Notes |
|---|---|---|
| Camera | expo-camera | Photo and video capture |
| Location | expo-location | Foreground and background tracking |
| File system | expo-file-system | Read/write/download files |
| Push notifications | expo-notifications | Local and remote push |
| Biometrics | expo-local-authentication | Face ID, Touch ID, fingerprint |
| Secure storage | expo-secure-store | Encrypted key-value storage |
| Image picker | expo-image-picker | Camera roll and camera access |
| Maps | react-native-maps | Google Maps / Apple Maps |
| Barcode scanning | expo-barcode-scanner | QR and barcode scanning |
For plugins without Expo equivalents, React Native’s native module system (TurboModules in the New Architecture) allows you to write platform-specific code in Swift/Kotlin and expose it to JavaScript.
Build and deployment with EAS
Expo Application Services (EAS) replaces the build and deployment complexity that both Xamarin and PhoneGap required:
EAS Build compiles your app in the cloud. No local Xcode or Android Studio configuration needed for CI/CD. Builds are triggered from the command line or from GitHub Actions.
EAS Submit handles App Store and Play Store submission directly.
EAS Update enables over-the-air JavaScript bundle updates without going through store review. This is a significant advantage for hot-fixing issues in production.
# Build for both platforms
eas build --platform all
# Submit to stores
eas submit --platform ios
eas submit --platform android
# Push an OTA update (JS-only changes)
eas update --branch production --message "Fix order total calculation"
This is a dramatic simplification compared to Xamarin’s MSBuild-based build chain or PhoneGap Build (which was discontinued).
What we have seen in practice
[CLIENT EXAMPLE: Field services company, PhoneGap app for job scheduling with camera capture, offline data sync, and GPS tracking (~20k LOC JavaScript). Migrated to React Native with Expo over 5 weeks. Business logic (scheduling algorithms, API clients, validation) was converted to TypeScript with ~55% AI-authored code. UI was rebuilt screen-by-screen using NativeWind. Push notifications reimplemented with expo-notifications (an improvement over the Cordova plugin). Offline sync rebuilt with WatermelonDB. Key improvement: EAS Update enables same-day fixes without store review, which was impossible with PhoneGap.]
[CLIENT EXAMPLE: Property management company, Xamarin.Native app (separate iOS and Android codebases) with 35 screens, camera/document scanning, and Bluetooth LE for smart locks. Migrated to React Native over 10 weeks. The separate platform codebases were consolidated into a single React Native codebase. Bluetooth LE integration used react-native-ble-plx. Document scanning used expo-camera with custom image processing. AI-assisted development handled the C# to TypeScript business logic translation (~50% AI-authored). Key lesson: consolidating two platform-specific codebases into one React Native codebase cut the ongoing maintenance surface in half.]
[CLIENT EXAMPLE: Retail company, Xamarin.Forms loyalty app with 22 screens, barcode scanning, push notifications, and in-app payments. Evaluated for both MAUI and React Native. Chose React Native because the team wanted to hire React developers for their web platform simultaneously. 7-week migration with Expo. Payment integration used Stripe’s React Native SDK (a significant improvement over the Xamarin Stripe binding). AI-assisted tooling handled data model translation and API client generation. Total AI-authored code: ~50%.]
Timeline expectations
| App complexity | Screens | Native integrations | Typical timeline |
|---|---|---|---|
| Simple | Under 15 | 1-2 (camera, location) | 4-6 weeks |
| Moderate | 15-40 | 3-5 (push, biometrics, offline) | 6-10 weeks |
| Complex | 40-80 | 5+ (Bluetooth, payments, AR) | 10-14 weeks |
| Very complex | 80+ | Custom native modules | 14+ weeks |
These timelines include AI-assisted development. Without AI tooling, add 40-60% to the business logic translation and component scaffolding phases.
Next steps
If you are evaluating React Native as a migration target, start with the mobile migration playbook for the full assessment framework.
For the comparison with MAUI, see our honest enterprise comparison.
For IP considerations around AI-generated code, see Who Owns AI-Written Code?.
For the general modernisation decision framework, see Modernise, Rebuild, or Replace.
Ready to plan your migration? Book a free Mobile Migration Assessment consultation.
Frequently asked questions
Is React Native production-ready for enterprise apps?
Should we use Expo or bare React Native?
How do we handle our C# backend if the mobile app moves to React Native?
Can our C# developers learn React Native?
How does AI help with a migration that involves a language change?
Related guides
Modernise, Rebuild, or Replace: A Decision Framework for Legacy Systems
Six modernisation strategies explained in plain language. Decision criteria, cost and risk comparisons, and how AI-augmented delivery changes which options are viable.
Signs Your Legacy System Is Costing You More Than You Think
Legacy systems hide their true costs in maintenance burden, talent risk, security exposure, and missed opportunities. Eight warning signs and how AI-augmented analysis reveals the full picture.