What is React Native? Architecture, Expo, and Flutter compared
Contents
React Native gets pitched as a single answer to 'write once, run everywhere,' but the real question senior engineers ask is narrower: how does its architecture actually work, and where does it break down? The framework-vs-library debate, the Expo confusion, and the Flutter comparison all trace back to one thing, the JavaScript-to-native bridge, and what replaced it.
This breaks down React Native's current architecture (Fabric, TurboModules, JSI, Hermes), clears up its relationship to React and Expo, and gives a straight answer on Flutter, web support, and when it's genuinely the right call.
How does React Native work? Fabric, TurboModules, JSI, and Hermes
React Native's new architecture answers this directly: Fabric, TurboModules, and JavaScript Interface (JSI) replace the old asynchronous bridge, letting JavaScript and native code call each other synchronously instead of queuing messages through a serialized bridge. React Native, Meta's open-source framework, now renders through this pipeline by default.
Fabric is the render layer. It builds and commits the native UI tree directly, replacing the old shadow-tree diffing that ran through the bridge. TurboModules replace the legacy native-module registry, loading native code lazily instead of eagerly bootstrapping every module at startup. JSI is the connective layer underneath both: a lightweight interface that lets JavaScript hold direct references to native objects, skipping JSON serialization entirely.
Hermes, Meta's JavaScript engine, compiles bytecode ahead of time and works with JSI to cut startup latency.
Meta shipped bridgeless mode as the default starting with React Native 0.76 in late 2024, according to Meta's engineering blog. The async bridge is deprecated and should not appear in new builds.
On Netguru's builds, this pipeline is where react-native-screens navigation and MMKV-based storage actually pay off: native calls avoid the serialization tax the old bridge charged on every frame.
What is the React Native bridge, and is it still used?
No. The async bridge is deprecated, and as of the new architecture rollout React Native does not use it by default. If you are starting a project today, you will not touch the legacy bridge at all.
The question still matters for existing apps, because plenty are running on it. Two quick checks tell you where you stand: a project on React Native 0.76 or later with newArchEnabled set is bridgeless, and any dependency still calling RCTBridge directly, or shipping only a legacy native module, has not been migrated.
Migration is mostly a dependency problem rather than an application-code one. Most app code carries over untouched; the work sits in third-party native modules that need a TurboModule-compatible version, and in any custom native module written against the old registry. Libraries that were already JSI-backed, MMKV among them, need the least work.
In our own React Native builds, migrating storage to JSI-backed bindings and rebuilding navigation on react-native-screens exposed how much of the old bridge's overhead was invisible until it was gone.
What is Metro bundler in React Native?
Metro bundler is the JavaScript bundler built specifically for React Native, and it runs on Node.js to transform, resolve, and serve your app's JavaScript modules to the native runtime. Metro is not Webpack. It skips generic web-bundling features like CSS loaders and code-splitting for browser chunks, and instead optimizes for a single goal: fast rebuilds during native app development.
Metro's dependency graph is designed for React Native's module resolution, platform-specific extensions (.ios.js,.android.js), Hermes bytecode compilation, and hot reloading during a native development cycle. According to React Native's official architecture documentation, Metro handles source transformation and bundling before Hermes compiles the output to bytecode ahead of time.
You need Node.js installed locally because Metro itself is a Node.js process: it watches your file system, resolves imports, and serves bundles over HTTP to the Metro dev server your simulator or device connects to.
Is React Native a framework or a library?
React Native is a framework, not a library. React itself is a library, an open-source one Meta uses to render UI components from JavaScript, and nothing more. React Native brings a full application framework on top: native navigation primitives, platform APIs, a build pipeline, and the Metro bundler, turning a rendering library into something that ships real apps.
The distinction is functional, not academic. React gives you components and a render lifecycle. React Native decides how those components map to native UIKit and Android View instances through Fabric, and how JavaScript calls into native code through TurboModules and the JavaScript Interface (JSI), none of which React itself has any concept of.
Meta open-sourced both projects but maintains them on separate release cadences, React Native version bumps don't track React's core library updates. If you're comparing stacks, treat the choice as framework-level, alongside Flutter or a native SDK, not as picking a rendering dependency.
React Native vs React: What's the difference?
React renders UI to the browser's DOM using HTML elements. React Native renders to native UI components instead, View, Text, Image, which map directly to platform widgets: UIView on iOS, android.widget on Android. That's the core split: one targets the DOM, the other targets native views through the platform's own rendering layer, not a webview.
React is the open-source library Meta released in 2013 to manage component state and diffing. React Native, which followed in 2015, reuses that same component model but swaps the renderer underneath it. A <div> in React becomes a <View> in React Native, and instead of CSS you style with a JavaScript object that maps to native layout properties (Yoga, under the hood).
The practical consequence: a React Native app looks and behaves like a native app because it is one, not a webview wrapped in a shell. React, by contrast, only ever produces a DOM tree for a browser to paint.
The two also serve largely separate developer populations despite sharing a component model: in Stack Overflow's 2024 Developer Survey, React Native and Flutter each sat around 9% usage among professional developers, while React itself was used by roughly 40%.
What is Expo in React Native?
Expo is a framework and toolchain built on top of React Native that packages the Metro bundler, a curated native module library, and cloud build services (EAS Build) into one workflow, removing most native project setup from day one.
Managed workflow keeps native code out of your repository entirely. There's no Xcode or Android Studio project to touch; Expo's SDK modules cover camera, location, and push notifications, and EAS handles signing and store submission. Bare workflow exposes the raw ios/ and android/ directories, giving direct access to native code and third-party native SDKs that Expo doesn't wrap.
"Ejecting" used to mean a one-way move from managed to bare. Config plugins replaced that with continuous native generation, so teams can add native code without abandoning Expo's build pipeline. According to the Expo changelog, Expo SDK 52 enables React Native's New Architecture by default for new projects, a step Meta's engineering team frames as central to the framework's bridgeless rollout.
Reach for bare workflow when a native module needs direct storage access, the kind of constraint that shows up when wiring in something like MMKV. Managed workflow fits most product teams shipping standard native features without custom native code.
Flutter vs React Native: Which one should you choose?
React Native wins when your team already knows JavaScript and TypeScript and you need native modules for camera, biometrics, or Bluetooth without writing platform code by hand. Flutter wins when pixel-perfect custom UI matters more than reusing web talent, since Dart renders every widget itself rather than mapping to native components.
The practical difference comes down to rendering. React Native's new architecture compiles JSX into actual native UIKit and Android View components through Fabric, so a <View> renders as a real native view, not a canvas-drawn shape. Flutter renders everything through Skia (moving to Impeller), which gives it more visual consistency across platforms but means your app never quite looks 'native' on either OS.
These rendering trade-offs are central to choosing between the two frameworks for your next mobile project.
Adoption data backs both up: Stack Overflow's 2024 Developer Survey puts React Native and Flutter within a few points of each other among professional developers, with React Native holding an edge in enterprises that already run React on the web.
Our view: pick React Native if you have an existing React or Node team, need deep native integration (we've shipped MMKV-backed storage and react-native-screens navigation on production apps), or want Hermes's faster startup and lower memory footprint out of the box. Pick Flutter for greenfield teams with no JS investment and heavy custom-animation requirements.
Netguru builds production apps in both, but our deeper bench sits in React Native. We saw this in practice with METRO Brazil: +70% increase in daily active users within the first three months.
Is React Native good for mobile app development?
React Native is a solid choice for most mobile app development when a team wants one JavaScript and TypeScript codebase that still renders through native UI components rather than a WebView. Built and maintained by Meta, React Native maps View, Text, and Image directly onto native UIKit and Android widget equivalents through Fabric, so the interface a user touches is genuinely native, not an emulation.
That is the core difference from fully native iOS or Android development: native development means separate Swift/Kotlin (or Objective-C/Java) codebases maintained in parallel, while React Native lets one team ship both platforms and drop into native code only for performance-critical modules through TurboModules. Still, React Native isn't always the right fit, and knowing when it falls short can save a team from costly rework.
Where React Native earns its keep is app categories dominated by business logic, forms, data fetching, and standard navigation, marketplaces, fintech dashboards, internal tools, content apps. In our MMKV storage benchmark work, synchronous key-value storage removed the async-bridge overhead that used to make simple read/write operations feel sluggish on older React Native versions.
Our react-native-screens navigation build showed native stack transitions matching platform-native feel once the app moved off the legacy bridge entirely.
Where it struggles: apps leaning on bleeding-edge platform APIs the same week Apple or Google ship them, or apps needing frame-perfect custom rendering, like Flutter's Dart-drawn widgets. Stack Overflow's developer survey consistently ranks React Native among the most-used cross-platform frameworks, which matters for hiring and long-term maintenance, not just initial build speed.
Before committing, it's worth weighing its trade-offs to see whether the framework's strengths outweigh its limitations for your specific use case.
For CTOs weighing it, the honest framing is: React Native is good for mobile app development when native UI fidelity matters more than pixel-level custom rendering, and when the team already has React depth to reuse.
Can React Native be used for web apps?
Yes, but through a separate project, not the core framework. React Native itself renders to native UIKit and Android views via Fabric, so it has no browser output on its own.
The bridge to the web is react-native-web, an open-source library maintained outside Meta's core React Native repo that maps the same View, Text, and Image primitives to DOM elements and CSS, letting one component tree ship to iOS, Android, and browser targets.
That is a different architecture from WebView-based hybrid apps, which embed an actual browser instance inside a native shell and load HTML/JS content at runtime. React Native apps render native widgets directly; WebView hybrid apps render a web page pretending to be an app. Expo's web target builds on react-native-web, so teams already using Expo Router get a web build with minimal extra configuration.
We'd recommend react-native-web only when the web build is secondary to a native-first product. A team building web-first should default to plain React, since react-native-web trades some rendering fidelity and bundle size for code sharing.
FAQ: Props, state, and components
What is React Native Fabric?
What are props in React Native?
What is FlatList and when should you use it?
ScrollView for anything more than a short, fixed set of items, since ScrollView mounts every child at once.
Does React Native support TypeScript?
What state management do React Native apps typically use?
Building a React Native app? Talk to engineers who've shipped it
Documentation answers what React Native is. It won't tell you whether Fabric and TurboModules fit your existing native codebase, or whether Hermes will choke on your bundle size.
Our engineers run React Native in production daily: Storybook-driven component libraries, MMKV storage migrations, react-native-screens navigation rebuilds. We give teams consistent support across channels, from architecture reviews to native module debugging, around the clock, not a generic sales pitch. For teams building complementary web platforms, our React web development team applies the same production rigor to component architecture and performance.
If you're weighing React Native against Flutter, or planning a new-architecture migration, talk to our team.
