DEV Community

Cover image for React Native vs. Flutter vs. Native: Why Cure.fit Rebuilt Its Navigation From Scratch
Ciphemic academia
Ciphemic academia

Posted on Originally published at ciphemicacademia.in

React Native vs. Flutter vs. Native: Why Cure.fit Rebuilt Its Navigation From Scratch

React Native vs. Flutter vs. Native: Why Cure.fit Rebuilt Its Navigation From Scratch

Cure.fit, the Indian fitness platform, had built its app on React Native since day one. Then they hit a wall that kept showing up in the same place: animations. The bottom navigation bar, the kind of UI every user touches constantly, never felt right, and the team traced the problem specifically to React Native's architecture. Their fix wasn't a patch, it was rebuilding the entire bottom navigation layer in Flutter, piece by piece, until the whole experience ran noticeably smoother. A separate, independent benchmark that rewrote the same simple app three times, once native, once in Flutter, once in React Native, measured Flutter's memory footprint at 23MB against React Native's 27MB, with the native version at 14MB, a real, measurable gap between all three, not just a feeling.

These two data points capture the actual decision you're making when you pick a mobile stack: not "which one is popular," but how much of that 14MB-to-27MB gap your specific app can afford to give up in exchange for faster, cheaper development. This guide compares all three honestly, what each one actually does under the hood, where the real numbers come from, and how to decide before you've built a year of app on an architecture you'll later have to rebuild, the way Cure.fit did.

If mobile fundamentals are still new ground, our Mobile Engineering roadmap covers what this comparison builds on.

This post originally appeared on the Ciphemic Academia blog.

The Short Version

  • Native development (Swift/Kotlin, separately for iOS and Android) gives you the best possible performance and full platform access, at the cost of building and maintaining two separate codebases.
  • React Native renders using actual native platform widgets, controlled from JavaScript through a "bridge," letting web developers reuse familiar skills, with real architectural overhead exactly where Cure.fit hit its wall.
  • Flutter draws its own UI from scratch using its own rendering engine, skipping native widgets entirely, which gives it more consistent performance across platforms, at the cost of a less familiar language (Dart) for most teams.

If you want one default: start with React Native if your team already knows JavaScript/React, start with Flutter if you're optimizing for consistent performance and don't mind learning Dart, and go native only once you have a specific, measured reason the other two can't satisfy.

What All Three Are Actually Trying to Solve

Before the differences, the shared problem, since this is what every mobile approach is answering:

  • Rendering a UI people can touch and interact with smoothly: all three ultimately have to draw pixels and respond to touch with low enough latency that it feels instant
  • Accessing device capabilities: camera, GPS, push notifications, sensors, every approach needs a path to the platform's native APIs
  • Shipping to both iOS and Android: even "native" development means solving this problem twice, just with two separate codebases instead of one
  • Keeping development sustainable over time: all three need to remain maintainable as a team and a codebase grow, not just work well on day one

The real difference is architectural: how each approach gets from your code to pixels on the screen, and that architecture is exactly where Cure.fit's animation problems and the thoughtbot benchmark's memory numbers both originate.

Native Development

What it actually is: building genuinely separate apps for iOS (typically Swift) and Android (typically Kotlin), each using the platform's own UI framework and talking directly to the operating system with no intermediate layer at all.

A small example (a button, Swift):

let button = UIButton(type: .system)
button.setTitle("Checkout", for: .normal)
button.addTarget(self, action: #selector(checkout), for: .touchUpInside)
Enter fullscreen mode Exit fullscreen mode

Where it shines:

  • Best possible performance: no bridge, no abstraction layer, direct access to the platform's own rendering pipeline, which is exactly why the thoughtbot benchmark found native using the least memory (14MB) of the three
  • Full, immediate platform access: new OS features and APIs are available to native code first, often before cross-platform frameworks catch up
  • Platform-idiomatic UI by default: native components automatically match each platform's look, feel, and accessibility behavior without extra work
  • No framework-layer bugs to debug around: you're working directly with Apple's and Google's own tools and documentation, with nothing else in between

Where it struggles:

  • Two full codebases: essentially building and maintaining two separate applications, in two separate languages, which is real, ongoing engineering cost
  • Slower feature development: every feature gets built twice, once per platform, which is a genuine velocity cost most teams feel immediately
  • Requires two skill sets on the team: hiring and retaining both strong iOS and strong Android engineers is a real organizational cost smaller teams often can't absorb

Who this suits: apps where performance is genuinely critical (heavy animation, gaming, AR/VR), teams with the resources to maintain two codebases well, and situations where deep platform-specific integration matters more than development speed.

React Native

What it actually is: a framework where you write UI logic in JavaScript and React, and React Native translates your component tree into calls that render using the platform's actual native widgets, through a communication layer historically called "the bridge." Your JavaScript doesn't draw the UI directly; it instructs the native side what to draw.

A small example (the same button, React Native):

<TouchableOpacity onPress={checkout}>
  <Text>Checkout</Text>
</TouchableOpacity>
Enter fullscreen mode Exit fullscreen mode

Where it shines:

  • Massive talent pool: any team with React or JavaScript experience can contribute meaningfully with a relatively short ramp-up
  • Genuinely native UI components: because it renders actual platform widgets rather than drawing its own, UI elements inherit native look-and-feel and accessibility behavior by default
  • Huge ecosystem: a large library ecosystem and strong community support cover most common app needs without custom native code
  • Hot reload and fast iteration: changes reflect almost instantly during development, which speeds up the build-test loop considerably

Where it struggles:

  • The bridge is a real architectural cost: every interaction between JavaScript and native code crosses that bridge, and Cure.fit's own engineering write-up specifically traced their animation and bottom-bar problems to this layer, not to a specific bug they could just patch
  • Performance ceiling for heavy UI work: complex animations and gesture-heavy interactions are exactly where the bridge's overhead becomes visible to users, as Cure.fit experienced directly
  • Version and dependency churn: the React Native ecosystem has historically had more breaking changes and upgrade friction than some teams expect going in

Who this suits: teams with strong existing JavaScript/React skills, apps without extremely heavy custom animation requirements, and products that benefit from a large, mature plugin ecosystem.

Flutter

What it actually is: a UI toolkit from Google where you write in Dart, and Flutter renders every pixel itself using its own graphics engine (Skia, with newer Flutter versions moving toward Impeller), completely bypassing native platform widgets. Nothing is translated to native UI components; Flutter draws its own UI from scratch on both platforms.

A small example (the same button, Flutter):

ElevatedButton(
  onPressed: checkout,
  child: Text('Checkout'),
)
Enter fullscreen mode Exit fullscreen mode

Where it shines:

  • Consistent performance across platforms: since Flutter draws everything itself rather than bridging to native widgets, iOS and Android apps behave far more consistently, which is exactly why Cure.fit chose Flutter specifically for its animation-heavy navigation layer
  • Closer to native-level performance: the thoughtbot benchmark found Flutter's resource usage (23MB) meaningfully closer to native (14MB) than React Native's (27MB) in that specific test
  • Single codebase, true pixel-level control: since Flutter isn't constrained by native widget behavior, teams get precise, consistent control over complex custom UI and animations
  • Strong tooling and hot reload: Flutter's development experience, including fast iteration, is widely regarded as a genuine strength

Where it struggles:

  • Dart is a real learning curve: unlike React Native's JavaScript, Dart is a less widely known language, which is real onboarding friction for most existing web or mobile teams
  • UI doesn't use native widgets: because Flutter draws everything itself, platform-specific look-and-feel updates (new OS-level UI changes) don't arrive automatically the way they sometimes do with React Native's native-widget approach
  • Smaller long-term talent pool than JavaScript: while growing quickly, the pool of experienced Flutter/Dart developers remains smaller than the React/JavaScript pool

Who this suits: teams optimizing specifically for consistent, high-quality UI and animation across platforms, projects without an existing deep investment in JavaScript, and exactly the kind of animation-heavy component Cure.fit chose to rebuild.

Side-by-Side Comparison

Native React Native Flutter
Language Swift (iOS), Kotlin (Android) JavaScript Dart
Rendering approach Platform's own UI framework Native widgets via a bridge Flutter's own engine, no native widgets
Codebases Two, separate One, shared One, shared
Measured memory use (benchmark) 14MB 27MB 23MB
Performance ceiling Highest Lower, bridge overhead Closer to native than React Native
Talent pool Two specialized skill sets Largest (JS/React) Smaller, growing
Best for Performance-critical, heavy native integration Teams with strong React skills, standard app UI Consistent cross-platform UI, animation-heavy screens

How This Fits a Career Path

  • Mobile Engineer (general): understanding all three, not just one, is increasingly the expectation, since real companies (Cure.fit included) mix approaches rather than picking one dogmatically
  • Frontend-to-mobile transition: React Native is the natural bridge for an existing React developer; our React & Frontend roadmap covers the web-side fundamentals that transfer directly
  • Cross-platform specialist: Flutter is worth deliberate investment if you're aiming at roles optimizing for consistent UI and animation quality across platforms
  • Platform or performance-focused roles: native development remains the standard where the thoughtbot-style performance gap genuinely matters to the product (gaming, AR, heavy real-time graphics)

How to Choose Without Overthinking It

  1. Start with your team's existing skills. Strong JavaScript/React team? React Native removes a real learning-curve cost. No strong investment either way? Flutter's more consistent cross-platform behavior is worth the Dart learning curve for many teams.
  2. Identify your actual animation and performance requirements early. Cure.fit didn't start with Flutter, they migrated specifically once a real, measured UI problem appeared. If your app is animation-light, React Native's bridge overhead may never become a real issue.
  3. Don't default to native "to be safe." Two codebases is a real, ongoing cost; reserve native for situations with a specific, articulable performance or platform-access requirement the other two can't meet.
  4. Consider a hybrid approach for an existing app. Cure.fit's "Add-to-App" style migration, replacing just one problematic screen or flow with Flutter inside an existing React Native app, is a real, lower-risk pattern worth knowing about rather than an all-or-nothing rewrite.

A note on honesty: the thoughtbot benchmark's 14MB/23MB/27MB numbers came from one simple timer app on specific devices; your app's real numbers will depend heavily on what you're actually building. Cure.fit's decision was driven by a specific, felt problem in one screen, not a blanket verdict against React Native. Measure your own app's pain points before committing to a framework based on someone else's numbers, including these ones.

Common Mistakes When Learning Mobile Development

  • Picking a framework before identifying your actual UI complexity. A simple CRUD-style app rarely needs to worry about the bridge-overhead problems that drove Cure.fit's migration.
  • Assuming "cross-platform" means identical performance to native. The real benchmark gap (14MB vs. 23MB vs. 27MB) is small for most apps, but it's not zero, and heavy animation is exactly where it shows up.
  • Underestimating Dart's learning curve for Flutter. It's a real, if often overstated, cost; budget genuine ramp-up time for a team new to it.
  • Rewriting an entire app instead of migrating the problem screen. Cure.fit's incremental, screen-by-screen approach is a lower-risk pattern than an all-at-once rewrite most teams should consider first.
  • Treating framework choice as permanent and un-revisitable. Real companies, Cure.fit included, have mixed frameworks within one app when a specific part of the product demanded it.

Frequently Asked Questions

Should a beginner learn React Native, Flutter, or native development first?

If you already know JavaScript and React, React Native gives you the fastest path to a working app. If you're starting fresh with no strong language preference, Flutter's consistent cross-platform behavior and strong tooling make it a genuinely good first choice too.

Is React Native being replaced by Flutter?

No. Both remain widely used in production, often by the same companies for different parts of their app, as Cure.fit's own hybrid approach shows. React Native's architecture has also continued to evolve specifically to reduce the bridge overhead that caused problems like Cure.fit's.

Does Flutter always perform better than React Native?

Not universally, but it was meaningfully closer to native in the specific thoughtbot benchmark cited above, and Cure.fit's real production experience with animation specifically favored Flutter. Your own app's results will depend on what you're actually building.

When does the performance difference between these frameworks actually matter?

Specifically in animation-heavy, gesture-intensive, or otherwise performance-critical UI, exactly the kind of bottom-navigation problem that pushed Cure.fit to migrate. A typical CRUD or content-display app is far less likely to hit this ceiling with either framework.

Can I mix native, React Native, and Flutter in one app?

Yes, and Cure.fit's real migration is a direct example, they embedded Flutter views inside an existing React Native app's navigation rather than rewriting everything at once.

How do interviewers evaluate this topic?

Usually by asking you to reason about trade-offs for a specific scenario, team skills, performance needs, timeline, rather than testing for a fixed framework preference. Being able to explain why a real team like Cure.fit chose to migrate, and what specifically drove that decision, is exactly the kind of reasoning that signals real experience.

Build the Judgment, Not Just the Framework Skill

The real lesson from Cure.fit's migration and the thoughtbot benchmark isn't "Flutter beats React Native," it's that both teams measured a specific, real problem before making a change. Explore the Mobile Engineering roadmap to build the skills that let you make that same evidence-based call on your own projects.

Top comments (0)