Table of Contents
- Why this guide
- Summary at a glance
- Minimal working examples
- Quickstart
- Performance in 2025
- Interop and native APIs
- UI development experience
- Ecosystem, packages, and tooling
- Testing and CI/CD
- When to choose which
- Pitfalls and gotchas
- Performance tips
- Migration notes for RN teams sampling Flutter
- Decision checklist
- Tiny FAQ
Why this guide
You build mobile apps and need a concrete 2025 view on React Native (RN) vs Flutter. This guide is practical, code-first, and tuned for React Native developers evaluating Flutter.
Summary at a glance
Area | React Native (2025) | Flutter (2025) |
---|---|---|
Language | TypeScript/JavaScript | Dart |
Rendering | Native widgets via Fabric | Custom engine (Impeller/Skia) |
Performance | Very good with Hermes + Fabric + TurboModules | Excellent, consistent across platforms |
Ecosystem | Strong JS ecosystem, many platform libs | Cohesive plugin ecosystem, fewer platform gaps |
UI Look & Feel | True native look by default | Pixel-perfect custom rendering, consistent |
Team Skills | Easy for web/React teams | Faster for teams new to React, but Dart learning curve |
App Size | Smaller for simple apps, can grow with deps | Typically larger base size |
Hot Reload | Fast Refresh | Hot Reload/Restart |
Desktop/Web | Community and Expo support improving | First-class mobile, good desktop/web via Flutter |
Bottom line: Choose RN if you want native look, JS/TS skills reuse, and tight platform interop. Choose Flutter if you value consistent performance, custom UI, and a single toolkit across targets.
Minimal working examples
React Native (TypeScript, Fabric-ready)
// App.tsx
import React from 'react';
import {SafeAreaView, Text, Pressable, StyleSheet} from 'react-native';
export default function App() {
const [count, setCount] = React.useState(0);
return (
<SafeAreaView style={styles.container}>
<Text style={styles.title}>RN Counter</Text>
<Text testID="count">{count}</Text>
<Pressable accessibilityRole="button" onPress={() => setCount(c => c + 1)}>
<Text style={styles.button}>Increment</Text>
</Pressable>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {flex: 1, alignItems: 'center', justifyContent: 'center'},
title: {fontSize: 20, marginBottom: 12},
button: {padding: 8, color: '#0a7', fontWeight: '600'},
});
Flutter (Dart)
// lib/main.dart
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const CounterPage(),
debugShowCheckedModeBanner: false,
);
}
}
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flutter Counter')),
body: Center(child: Text('$_count', style: const TextStyle(fontSize: 24))),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => _count++),
child: const Icon(Icons.add),
),
);
}
}
Quickstart
React Native
- Install prerequisites: Node LTS, Java 17 (Android), Xcode (iOS).
- Create app (bare):
npx react-native@latest init RnApp --template react-native-template-typescript cd RnApp npx react-native start
- Run platform:
npx react-native run-ios npx react-native run-android
- Optional (Expo):
npx create-expo-app ExpoRnApp -t expo-template-blank-typescript cd ExpoRnApp && npx expo start
Flutter
- Install Flutter SDK and platform toolchains.
- Create app:
flutter create flutter_app cd flutter_app flutter run
- Hot reload: save file; use
r
/R
in terminal for reload/restart.
Performance in 2025
- Startup time:
- RN: Hermes bytecode precompilation and Fabric reduce startup costs; keep JS bundle lean.
- Flutter: AOT-compiled Dart; predictable startup, larger base size.
- Rendering:
- RN: Native UI threads; Fabric improves sync with JS runtime; 120 Hz support depends on platform widget support.
- Flutter: Impeller engine reduces jank on iOS/Android; excellent 120 Hz handling.
- Animations:
- RN Reanimated/Animated with Layout/JSI deliver smooth 60–120 fps when offloaded to native/Worklets.
- Flutter: Built-in animation framework is highly consistent and performant.
- Memory/CPU:
- RN: JS heap + native; monitor with Flipper. Avoid large object graphs and unnecessary re-renders.
- Flutter: Single engine + widget tree; watch widget rebuilds and image cache.
Interop and native APIs
- React Native
- TurboModules and JSI offer low-overhead native bindings.
- Easy reuse of existing native SDKs via minimal wrappers.
- Ideal when you need niche device APIs or to embed RN into existing native apps.
- Flutter
- Platform Channels and FFI for native/host interop.
- Consistent, but requires boilerplate when bridging complex streams or high-frequency calls.
UI development experience
- RN
- Uses platform-native components by default; matches platform look automatically.
- Styling with Flexbox; many devs reuse web/React patterns.
- Flutter
- Everything is a widget; Material/Cupertino ready-to-use.
- Full control over pixels; custom UI is often faster to implement.
Ecosystem, packages, and tooling
- RN
- Leverage NPM/TypeScript, Metro, Jest, ESLint, and community libraries.
- Expo accelerates delivery (OTA updates, assets, EAS build) if you accept its managed constraints.
- Flutter
- Cohesive
pub
ecosystem; strong first-party plugins. - Great DevTools (widget inspector, performance overlays) out of the box.
- Cohesive
Testing and CI/CD
- RN
- Unit: Jest + React Testing Library.
- E2E: Detox or Maestro.
- CI: Gradle/Xcode + fastlane or EAS.
- Flutter
- Unit/widget tests built-in (
flutter test
). - Integration tests with
flutter drive
orintegration_test
. - CI:
flutter build
across targets; consistent pipelines.
- Unit/widget tests built-in (
When to choose which
Choose React Native if:
- You have strong React/TS skills and want fast onboarding.
- You need deep native integrations or to incrementally adopt in an existing app.
- You want platform-native look and accessibility without extra tuning.
Choose Flutter if:
- You need custom, uniform UI across platforms and hardware.
- You want predictable performance and cohesive tooling.
- You target mobile plus desktop/web with one engine-first stack.
Pitfalls and gotchas
- React Native
- Mismatch between new architecture (Fabric/TurboModules) and old modules can cause runtime issues; prefer modules updated for the new arch.
- Hermes requires native build settings aligned (ProGuard/R8 rules, bytecode precompile); misconfig leads to crashes.
- iOS: CocoaPods version drift; always
pod repo update
and use consistent Ruby/Pods. - Android: Gradle plugin/JDK version mismatches; pin versions in
gradle.properties
. - Performance: avoid chatty bridges; move work to native/JSI or Reanimated worklets.
- Flutter
- Larger APK/IPA sizes; enable tree shaking, split per-ABI.
- Platform Views (embedding native views) can impact performance; batch operations.
- Plugin compatibility lags for niche device features; be ready to write platform code.
- Asset-heavy apps can grow memory; manage image cache and precache strategically.
Performance tips
- React Native
- Enable Hermes and the new architecture; use React 18 concurrent features cautiously.
- Memoize with
React.memo
,useCallback
,useMemo
. Use FlatList withgetItemLayout
. - Offload animations to native (Reanimated) and heavy work to native threads.
- Flutter
- Prefer const constructors; minimize rebuilds with
ValueListenableBuilder
or state management. - Use
RepaintBoundary
wisely; cache images; compress assets. - Profile with the Performance view; fix layout thrash and shader compilation.
- Prefer const constructors; minimize rebuilds with
Migration notes for RN teams sampling Flutter
- Start with a feature prototype in Flutter to validate workflows and UI feasibility.
- Expect 1–2 weeks to get comfortable with Dart idioms and widget composition.
- Reuse business logic via FFI or by hosting shared logic in backend services.
Decision checklist
- Team skills today (React/TS vs Dart/Flutter)?
- Target platforms and UI requirements (native look vs custom)?
- Need for niche native SDKs?
- Performance constraints (startup, animations, memory)?
- Build/release velocity and tooling preference?
Tiny FAQ
- Does React Native still need a bridge?
- The legacy bridge is being replaced by JSI/TurboModules; fewer bottlenecks in 2025.
- Is Flutter web production-ready?
- It works well for app-like UIs; for content-heavy sites, traditional web stacks may be leaner.
- Which has better hiring pool?
- React/TypeScript remains broader; Flutter talent is strong but smaller.
- Can I mix native screens?
- Yes. Both support adding a single screen or embedding into existing native apps.