Steven's Knowledge

Cross-Platform Comparison

Choosing between Flutter and React Native — rendering model, perf, team fit, native interop, ecosystem

Cross-Platform Comparison

Choosing a cross-platform framework is mostly a fit decision, not a "which is better" decision. Both Flutter and React Native ship apps at scale. The selection turns on existing skills, native-interop needs, design fidelity targets, and team size.

The Honest Short Version

QuestionPick FlutterPick React Native
Team comes from React/web?
Pixel-identical UI across platforms is a hard requirement?
Need to embed many native UI components?
Need consistent, high-fidelity custom animation across platforms?
Need to share code with a web app?Possible, with caveats✅ (RN + RN Web or RN + Next sharing logic)
Native interop is critical (lots of platform SDKs)?Workable
Want strongest typing out of the box?✅ (Dart)✅ (TS) — both fine

If the team's React skills are real and the app is mainly forms + lists + APIs, React Native is usually the lower-friction choice. If the app is highly designed, gesture-heavy, animation-heavy, or needs identical pixel output on Android and iOS, Flutter has the structural edge.

Rendering Model

This is the single biggest architectural difference.

Flutter

  • Owns the canvas. Flutter renders every pixel itself via Skia (or Impeller on iOS).
  • Widgets are not platform views; they're descriptions consumed by a custom renderer.
  • Pro: identical visuals across platforms, full control of every frame.
  • Pro: no JS/native bridge cost — Dart compiles to native AOT.
  • Con: native UI conventions (system fonts, native context menus, accessibility) must be re-implemented.
  • Con: embedding platform views (AndroidView, UiKitView) is comparatively expensive.

React Native

  • Uses platform views. Each component maps to a real UIView (iOS) or View (Android).
  • The new Fabric renderer brings a concurrent-rendering–aware model, but the leaves are still native views.
  • Pro: looks and behaves natively for free; accessibility plumbing via platform.
  • Pro: embedding existing native UI is straightforward.
  • Con: maintaining identical pixel output across platforms takes more effort.
  • Con: high-frequency UI updates historically pay bridge cost (mitigated by JSI, Reanimated, Fabric).

Language

AspectFlutter (Dart)React Native (TS/JS)
Compile outputAOT native (release), JIT (debug)JS bytecode via Hermes
Null safetySound, language-levelSound via TypeScript strict
Ecosystem sizeSmaller than JS, focusedLargest in the world (npm)
Hiring poolSmaller but growingVast (any React dev)
Hot reloadExcellent, with state preservedFast Refresh (component state preserved)
Concurrent / async modelIsolates + async/awaitSingle JS thread + workers + Reanimated UI thread

Dart's tooling is more uniform and easier to onboard. The JS ecosystem is bigger, but inconsistent — you choose between many state libraries, bundlers, and patterns.

Performance Profile

Both can hit 60 fps on mid-range hardware when used correctly. They fail in different ways:

Failure modeFlutterReact Native
Rebuild blowupWhole subtree rebuilds without const or SelectorWhole tree re-renders without memo/selector
Animation jankRare — runs on the UI thread by defaultIf you skip useNativeDriver / Reanimated
Long listsListView.builder virtualizationFlatList (config-heavy) or FlashList
Cold startSlower app size grows the binaryHermes makes parse fast; native init dominates
Heavy CPU workMove to IsolateMove to a worker (web-worker-like) or native module

The framework alone does not make an app fast or slow — discipline does.

Native Interop

ConcernFlutterReact Native
Sync method callMethodChannel (async only) or FFI (sync, C)TurboModule (sync supported) or JSI
Native UI embeddingAndroidView / UiKitView (perf cost)First-class — components are native views
CodegenPigeon (optional)Codegen (default in New Architecture)
FFI to C/C++First-class dart:ffiPossible via JSI
Plugin authoringPub package + platform codenpm package + platform code

If the app must surface many native SDKs (mapping, payments, telco, vendor identity), React Native usually has less friction. If you need fast sync access to C libraries, Flutter's FFI is excellent.

Code Sharing With Web

PathFlutterReact Native
One codebase to webFlutter Web (works, not pixel-perfect for content sites)RN Web (same components on web, mature)
Share logic with a separate Next.js appPainful (Dart ↔ TS)Trivial (TS everywhere)
Share design systemRe-implement in Flutter widgetsShare with a react-native-web package

If a web product is part of the strategy, React Native wins on logic sharing. Flutter Web is acceptable for app-like portals, less so for SEO-critical content sites.

Build, Deploy, OTA Updates

ConcernFlutterReact Native
Build toolingflutter build, single commandGradle (Android) + Xcode (iOS) — more moving parts
App size baseline~5 MB engine + assets~10 MB engine + Hermes + JS bundle
Over-the-air JS updateNot supported (binary AOT)CodePush, EAS Update, custom — JS bundle swappable
Compliance with store rulesStandardBe careful with OTA scope — Apple allows JS code updates only

OTA updates are a significant operational lever for React Native: ship fixes within hours, not through store review. Flutter cannot do this for Dart code.

Team & Hiring

RealityImplication
Web React developers outnumber Flutter developersRN ramps a new hire faster if they have React experience
Flutter developers cluster — fewer but more focusedMature Flutter shops report tighter conventions
Designer collaborationFlutter widgets are bespoke; designers tooling (Figma → Flutter) is improving but not standard. RN component libraries map naturally to native UI familiar to designers.

Ecosystem Snapshot (Practical)

NeedFlutter packageReact Native package
Navigationgo_router@react-navigation/native
State managementriverpod / bloczustand / @reduxjs/toolkit / TanStack Query
Server state cachemanual / flutter_riverpod async@tanstack/react-query
Formsreactive_forms / flutter_form_builderreact-hook-form + zod
Local DBdrift / isar / hiveop-sqlite / WatermelonDB / react-native-mmkv
Networkingdio / chopperfetch + interceptor / axios
Crash reportingSentry / Firebase CrashlyticsSentry / Firebase Crashlytics
Pushfirebase_messaging@react-native-firebase/messaging / Notifee
AnimationsImplicit + explicit + Rivereact-native-reanimated v3

Both ecosystems cover the typical app. RN edges out for telco-specific SDKs (more vendors ship Android/iOS-only SDKs and an RN wrapper than Dart bindings).

Migration Reality

Migrating an existing native app:

  • Brownfield is supported in both. Flutter has add-to-app, RN has standard hosting in UIViewController / Activity.
  • Maintenance teams report RN brownfield is smoother because the leaves are still native — less impedance with existing screens.
  • Greenfield: both excellent.

Decision Framework

Start with the team and the goal.

1. Existing React/web team that values code reuse with web?
   → React Native

2. Brand-led product, identical visuals everywhere, lots of custom animation?
   → Flutter

3. Many native SDKs, telco/finance/vendor integrations?
   → React Native (lower interop cost)

4. Tight perf budget, no JS to manage, full rendering control?
   → Flutter

5. Need OTA updates to ship fixes hourly?
   → React Native (CodePush / EAS Update)

6. Hiring is a real constraint?
   → Whichever your local market supplies more of (usually React Native)

Anti-Patterns Either Way

  • Choosing by hype, not fit. Both are mature; the answer changes per team.
  • Mixing both in one app. It's possible (separate modules), but doubles the operational burden — only do it as a migration step.
  • Underestimating designer friction. Flutter's bespoke widgets need a tighter design partnership; without it, apps look "Flutter-ish" rather than native.
  • Underestimating RN performance discipline. RN goes fast only when you respect bridge cost, list virtualization, and re-render scope.

TL;DR

  • React Native is the safer default for a web-heavy organization or one with many native SDK dependencies.
  • Flutter is the safer default when pixel-perfect cross-platform design and animation are core to the product.
  • Both ship apps at scale; the failure mode is undisciplined engineering, not the framework choice.

On this page