#react-native /

React Native vs Flutter: 2024 Cross-Platform Selection Guide

Comprehensive comparison of React Native and Flutter from performance, development experience, ecosystem, and hiring perspectives to help teams make informed cross-platform technology choices.

Goal

Choosing a cross-platform development framework is a key mobile technology decision. React Native and Flutter are currently the two most mainstream solutions, but their design philosophies and technical characteristics are quite different. This article compares these two frameworks from multiple dimensions to help teams make reasonable technology choices based on actual needs.

Background

Positioning of the Two Frameworks

React Native:
  Released: 2015
  Language: JavaScript/TypeScript
  Philosophy: Build native apps with Web technologies
  Rendering: Maps to native controls
  Backed by: Meta (Facebook)

Flutter:
  Released: 2017
  Language: Dart
  Philosophy: Custom rendering engine, one codebase for all platforms
  Rendering: Draws all pixels itself
  Backed by: Google

Core Differences

Rendering Mechanism

React Native:
  JavaScript → Bridge → Native controls → Native rendering
  - Uses platform native controls for rendering
  - Appearance matches native
  - Limited by platform control capabilities

Flutter:
  JavaScript → Dart → Skia engine → Pixels
  - Draws all UI itself
  - Consistent cross-platform appearance
  - Complete rendering control

Performance Comparison

| Dimension | React Native (New Architecture) | Flutter | |-----------|--------------------------------|---------| | Startup time | 0.5-1 second | 0.3-0.8 seconds | | Frame rate | 58-60 FPS | 60 FPS | | Memory usage | Medium | Medium-low | | Package size | Smaller | Medium | | Hot update | Supported (CodePush) | Not supported |

Development Experience

// Flutter: Dart language
class Counter extends StatefulWidget {
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _count = 0;
Widget build(BuildContext context) {
return Row(
children: [
IconButton(
icon: Icon(Icons.remove),
onPressed: () => setState(() => _count--),
),
Text('$_count'),
IconButton(
icon: Icon(Icons.add),
onPressed: () => setState(() => _count++),
),
],
);
}
}
// React Native: JavaScript/TypeScript
import { useState } from 'react';
import { View, Text, IconButton } from 'react-native';
function Counter() {
const [count, setCount] = useState(0);
return (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<IconButton
icon={{ name: 'remove' }}
onPress={() => setCount(count - 1)}
/>
<Text>{count}</Text>
<IconButton
icon={{ name: 'add' }}
onPress={() => setCount(count + 1)}
/>
</View>
);
}

Ecosystem Comparison

UI Component Libraries

| Dimension | React Native | Flutter | |-----------|--------------|---------| | Official components | React Native Paper | Material Design | | UI libraries | NativeBase, React Native Elements | Flutter Widget library | | Icons | react-native-vector-icons | flutter_icons | | Animations | react-native-reanimated | Flutter Animation |

Third-Party Libraries

| Dimension | React Native | Flutter | |-----------|--------------|---------| | Navigation | React Navigation, Expo Router | GoRouter, Navigator | | State management | Redux, Zustand, Jotai | Provider, Riverpod, Bloc | | Network requests | Axios, Fetch | Dio, http | | Local storage | AsyncStorage, MMKV | SharedPreferences, Hive | | Database | WatermelonDB, Realm | drift, sqflite |

Toolchain

| Dimension | React Native | Flutter | |-----------|--------------|---------| | IDE support | VS Code, Android Studio | VS Code, Android Studio, IntelliJ | | Debugging | Flipper, React DevTools | Flutter DevTools | | Testing | Jest, React Native Testing Library | flutter_test, integration_test | | CI/CD | Fastlane, EAS | Flutter CLI, Fastlane |

Project Type Adaptation

When to Choose React Native

✅ Already have a Web team
  - Team familiar with React/JavaScript
  - Can reuse Web business logic
  - Easier to hire JavaScript developers

✅ Need native appearance
  - App needs to match platform native style
  - Need to use platform-specific UI components

✅ Need hot updates
  - Quickly fix production bugs
  - Bypass app store review

✅ Small to medium applications
  - Fast development speed
  - Mature ecosystem, rich third-party libraries

When to Choose Flutter

✅ Pursuing performance
  - Need 60 FPS smooth animations
  - Sensitive to startup time

✅ High consistency requirements
  - Need iOS and Android to have completely identical appearance
  - Need to support Web and desktop

✅ Complex UI
  - Need custom drawing
  - Need complex animation effects

✅ New team/new project
  - No historical burden
  - Can build tech stack from scratch

Team Factors

Hiring Market

React Native:
  - Large JavaScript/TypeScript developer base
  - Web developers can quickly transition
  - Many React Native developers on the market

Flutter:
  - Relatively fewer Dart developers
  - Requires specialized training
  - But Dart language has a gentle learning curve

Learning Cost

| Dimension | React Native | Flutter | |-----------|--------------|---------| | Language | JavaScript/TypeScript | Dart | | Prerequisites | React experience helpful | No special requirements | | Learning curve | Gentle (with Web experience) | Medium (need to learn Dart) | | Documentation quality | Excellent | Excellent | | Community support | Active | Active |

Performance Benchmarks

Startup Time

Test environment: iPhone 12, Android Pixel 6

React Native (New Architecture):
  Cold start: 1.2 seconds
  Hot start: 0.4 seconds

Flutter:
  Cold start: 0.8 seconds
  Hot start: 0.3 seconds

List Scrolling

Test scenario: Fast scrolling of 1000-item list

React Native:
  Average frame rate: 58 FPS
  Frame drop rate: 3%

Flutter:
  Average frame rate: 60 FPS
  Frame drop rate: 1%

Memory Usage

Test scenario: Medium complexity application

React Native:
  Idle: 80 MB
  In use: 150 MB

Flutter:
  Idle: 60 MB
  In use: 120 MB

Migration Cost

React Native → Flutter

// Parts that need rewriting
1. All UI components
2. Navigation logic
3. State management
4. Native module integration
// Parts that can be reused
1. API call logic (needs rewriting to Dart)
2. Business logic (needs rewriting to Dart)
3. Design specifications

Flutter → React Native

// Parts that need rewriting
1. All UI components
2. State management
3. Native module integration
// Parts that can be reused
1. API call logic (needs rewriting to JavaScript)
2. Business logic (needs rewriting to JavaScript)

Real-World Cases

Companies Using React Native

  • Facebook: Their own product, earliest adopter
  • Instagram: Migrated from native to React Native
  • Shopify: E-commerce application
  • Discord: Social application

Companies Using Flutter

  • Google Pay: Payment application
  • BMW: Automotive application
  • Alibaba: Xianyu (Idle Fish)
  • Tencent: Multiple applications

Conclusion

There is no absolutely better framework, only more suitable choices. Key decision factors:

  1. Team background: If you have React experience, choose React Native; new teams can consider Flutter
  2. Performance requirements: For extreme performance, choose Flutter
  3. Consistency requirements: For completely consistent cross-platform appearance, choose Flutter
  4. Hot update needs: For hot updates, choose React Native
  5. Application scale: Both work for small to medium applications; for large applications, choose based on team circumstances

Recommendation: For most teams, if you already have React experience, React Native is the more pragmatic choice. For new projects pursuing performance and consistency, Flutter is worth serious consideration.

Technology selection is not a one-time decision. As both frameworks continue to evolve, choices will also change. Stay informed and adjust as needed.

Like this post? Tweet to share it with others or open an issue to discuss with me!