Comparison

One mobile codebase: Expo and React Native, or Flutter?

The verdict

If the people building this app already write React on the web, pick React Native with Expo. The reuse is not theoretical - types, validation schemas, API clients, and business logic move across unchanged, and the New Architecture has closed most of the historical performance gap. If you need identical pixels on both platforms, heavy custom animation, or you are staffing a dedicated mobile team from scratch, pick Flutter. It draws every pixel itself, which is exactly why the design comps match on both platforms and exactly why a native list never quite feels native. The deciding question is not which framework is better. It is whether this app is an extension of a web product or a mobile product in its own right.

Both sides settled a long-running argument in the last eighteen months. React Native's New Architecture - Fabric, TurboModules, JSI, and Hermes - is mandatory rather than optional: the legacy architecture was frozen in June 2025, React Native 0.82 was the first release to run entirely on the new one, and every Expo SDK from 55 onward enables it with no way to turn it off. Current as of this writing is Expo SDK 57, shipped 30 June 2026, on React Native 0.86. On the other side, Flutter's Impeller renderer is the default on both iOS and Android, which removed the shader compilation jank that dominated Flutter criticism for years.

React Native vs Flutter on the dimensions that decide it

Performance claims from either project are treated here as claims. The dimensions below are the ones you can verify on your own app, or that are structural rather than benchmarked.

Dimension React Native with Expo Flutter
Language and hiring TypeScript. The largest developer pool that exists, and the same one your web team is already hired from. Dart. A smaller pool, but candidates tend to be mobile specialists rather than web developers moving sideways.
Rendering Real platform views. A list scrolls with the OS scroll physics because it is the OS list. Its own rasterizer via Impeller. Every control is drawn by Flutter, so it looks the same everywhere by construction.
Design fidelity Follows platform conventions by default. Matching a pixel-exact cross-platform comp takes real effort. Pixel-exact on both platforms with no effort. Material and Cupertino are approximations you maintain yourself.
Performance ceiling The async bridge is gone. Synchronous native calls through JSI make CRUD, forms, and feed apps indistinguishable from native. AOT-compiled Dart with no interop layer at all. Still the safer bet for continuous animation and custom-drawn interfaces.
Code reuse with web High. Logic, types, and API clients are shared outright, and React Native Web extends that to components. Low in practice. Flutter web exists but is a poor fit for a marketing or content site, so most teams run two codebases.
Third-party SDKs npm plus Expo's module catalog. Commercial vendors nearly always ship a React Native binding first. pub.dev, which is well curated and first-party heavy. Vendor plugins usually exist now, sometimes a version behind.
Build and release pipeline EAS Build, Submit, and Update as a managed pipeline, including over-the-air JavaScript updates that skip store review. Excellent local tooling and a strong CLI, but you assemble CI yourself and there is no first-party over-the-air update path.
Upgrade pain Historically the weak point. Expo's newer, narrower SDK cadence - 57 exists mainly to move apps to RN 0.86 - is a deliberate fix. Generally smoother. Fewer moving parts because the framework owns the whole rendering stack.
Governance risk Meta plus Expo, a venture-funded company on the critical path for most teams' build pipeline. Google alone. The engineering is excellent; Google's track record with its own products is the standing worry.
Escape hatch to native Expo config plugins and TurboModules, or eject to a bare project. Well-worn paths in both directions. Platform channels and federated plugins. Clean, but you are writing Swift or Kotlin on the other side either way.

When each framework is the right call

Choose React Native with Expo when

  • A React web app already exists. Sharing the API client, the Zod schemas, and the domain types is a permanent saving, not a one-time one.
  • You need to ship a fix today. Over-the-air updates through EAS put a JavaScript change in front of users without waiting on app review.
  • Hiring is a constraint. You can staff this from the TypeScript pool, and a web developer is productive on the codebase in a week.
  • The app should feel like the platform: native navigation gestures, native pickers, native lists, native accessibility behavior.
  • You depend on commercial SDKs - analytics, payments, support chat, feature flags - where React Native bindings ship first and get fixed first.
  • The screens are forms, lists, feeds, and detail views. The New Architecture handles that class of app with no perceptible gap to native.

Choose Flutter when

  • The design is a brand, not a platform. If the comp must render identically on an iPhone and a five-year-old Android, Flutter gives you that for free.
  • The interface is animation-heavy or custom-drawn: a fitness tracker, a music app, a game-adjacent product, anything with continuous motion at 120 fps.
  • You are building a mobile team from scratch and there is no web codebase to reuse, so the JavaScript advantage evaporates.
  • You want fewer moving parts. One toolchain, one language, one renderer, and upgrades that touch fewer things.
  • You are targeting embedded or kiosk displays alongside phones, where owning the rendering surface is an advantage rather than a compromise.
  • Consistency across a long tail of cheap Android devices matters more than matching each platform's native conventions.

What changed in 2026, and what did not

The New Architecture becoming mandatory is the biggest structural change on the React Native side in a decade. The old asynchronous bridge - the thing every "React Native is slow" argument was actually about - is gone. Fabric renders synchronously, TurboModules load native modules lazily, and JSI lets JavaScript call into native code directly. Since Expo SDK 55 there is no opt-out, and the legacy path has been frozen since June 2025, so anyone still on it is on SDK 54 or older and accumulating debt. That is a hard forcing function, and it is the right one.

Expo's release strategy changed too, in a way that matters more than it sounds. SDK 57 was deliberately narrow: move apps to React Native 0.86 without turning the upgrade into a project. React Native upgrades have historically been the single most-cited reason teams regretted the framework, and a cadence of smaller, more frequent, lower-risk releases is the direct answer to it. Whether it holds is worth watching, but the intent is clear and the first release under it delivered.

On performance, be careful about the numbers you read. Flutter's compiled Dart and self-owned rasterizer genuinely avoid an interop layer that React Native still has, even a fast one, and Impeller genuinely eliminated a category of jank. That advantage is real and it is measurable on animation-heavy screens. It is also mostly irrelevant to an app that shows a list, a form, and a settings page - which describes most apps. Anyone telling you Flutter is categorically faster is over-generalizing from a benchmark that does not resemble your product, and anyone telling you React Native is now identical is over-generalizing from the opposite one.

What has not changed is the reuse asymmetry, and it is the strongest argument on this page. React Native shares a language, a type system, a package registry, and in many cases actual component code with a React web application. Flutter shares nothing with your web stack unless you are willing to ship Flutter web, and almost nobody should for a public-facing site. If a React web product exists, that single fact should outweigh most of the rest of this comparison.

The honest hedge in the other direction: if a designer owns the visual language and expects it honored exactly, React Native will fight you. Getting a custom design system to render identically across iOS and Android on top of real native components is ongoing work forever, and Flutter turns that into a non-problem. That is not a small thing for a consumer product whose differentiation is how it looks.

Official documentation is at docs.expo.dev, reactnative.dev, and flutter.dev. React Native's own documentation now recommends starting new projects with Expo, which is worth knowing before you evaluate the bare workflow.

Where this fits in a full stack

The mobile app stack guide assembles the rest of the build around either choice: backend, auth, push notifications, crash reporting, and store submission.

The backend decision usually comes next, and it interacts with this one - Supabase vs Firebase covers the offline sync question that matters far more on mobile than on the web.

If you chose React Native, the React hooks cheatsheet and Zustand vs Redux both apply to the app unchanged. More matchups are in the comparisons index.