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).
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
Migrating from .NET Framework to .NET 10: An AI-Assisted Approach with Claude Code
Step-by-step guide for migrating .NET Framework 4.x applications to .NET 10 using Claude Code and the .NET Upgrade Assistant. Real patterns, real code, real gotchas.
Legacy .NET Application Assessment: A Scoring Framework for Modernisation Readiness
A practical scoring framework to assess legacy .NET applications for modernisation readiness. Score across six dimensions and prioritise your migration programme.
Modernising Legacy .NET Applications with AI: The Enterprise Playbook (UK, 2026)
A structured approach to modernising legacy .NET Framework applications using AI-assisted development. Four pillars, real migration patterns, and practical guidance for enterprise teams.