React Native is a cross-platform mobile framework that lets you build iOS and Android apps from one JavaScript codebase while still rendering native UI components. This guide explains what React Native is, how its architecture works, where it fits best, and when native development may still be the better call.
Shipping the same mobile app twice, Swift for iOS and Kotlin for Android, means paying double. Development teams explain three-month Android delays while stakeholders watch iOS features ship first. Feature parity becomes a budgeting problem instead of a technical one, and every sprint compounds the divergence.
React Native helps reduce that redundancy. You write React components in JavaScript, render them as native views, and ship on both platforms from a single codebase. The framework delivers cross-platform native apps where JavaScript components render as real native UI elements, not web wrappers.
React Native powers production apps and has accumulated over 126,000 GitHub stars. This guide covers how the architecture works under the hood, the practical benefits for your team, how to get started, and where native development still makes more sense.
In Brief:
- React Native renders JavaScript components as genuine native UI elements on iOS and Android, not web wrappers, eliminating the need for duplicate Swift and Kotlin codebases.
- The 0.82 update describes the move away from the old async bridge toward JSI for direct C++ calls, which can help with animation smoothness and app startup.
- Leverage existing JavaScript talent and React patterns for mobile apps, with hot reloading that cuts feedback loops from minutes to seconds.
- React Native fits content-driven apps, B2B tools, and startup MVPs well, but native development can still make more sense for graphics-intensive games or bleeding-edge hardware features.
What Is React Native?
React Native is an open-source JavaScript framework by Meta that lets you build mobile apps with React components while delivering fully native user interfaces on iOS and Android.
When you write a View or Text element, React Native translates that component into the platform's actual UIView or android.view, with no WebViews involved. You get native performance and the look users expect from a platform-native app.
This separates it from web-wrapper approaches, which run HTML and CSS inside WebViews and can struggle with performance. React Native components map directly to the host platform's own UI widgets, so they automatically inherit OS-level accessibility APIs, system font rendering, and platform-standard interactions.
The framework follows a "Learn Once, Write Anywhere" philosophy. You reuse most code across platforms while dropping to native APIs when platform-specific features demand it.
Meta created React Native after their HTML5 mobile app performed poorly enough that the Zuckerberg quote called betting on web tech "the biggest mistake we made as a company." Engineer Jordan Walke built a prototype that rendered iOS UI elements directly from JavaScript threads. After validation in a 2013 hackathon, Facebook shipped production features with React Native by early 2015.
Since the 2015 open-source release, the framework has undergone a fundamental architectural overhaul. The 0.76 release made the New Architecture the default, and the 0.82 update says the legacy opt-out flags are no longer functional. The 0.84 release also describes Hermes V1 as the default JavaScript engine and the removal of legacy architecture components from the codebase.
How React Native Works Under the Hood
Understanding the rendering pipeline helps you make informed decisions about when the framework fits and where it might not. The architecture has changed significantly, so many older tutorials describe a system that no longer reflects the current direction of the project.
The Three-Thread Model (Legacy Context)
The original architecture ran your app across three threads. The JavaScript thread executed business logic using a JavaScript engine. When your code described UI components, the framework sent serialized JSON messages across an asynchronous bridge to the native layer, which constructed actual platform widgets. A shadow thread calculated layout via the Yoga engine.
// JavaScript Layer
function Greeting() {
return (
<View>
<Text>Hello, React Native</Text>
</View>
);
}
/*
Greeting() // JavaScript Thread
│ diff & batch
▼
Bridge (JSON message) // Background Thread
│ deserialize
▼
Native Module // UI/Main Thread
└─► UIView/TextView rendered on screen
*/For most interactions this pipeline performed well, though high-frequency updates could expose bridge overhead. Every call required JSON serialization, every response needed a callback, and all return values had to be JSON-serializable.
The New Architecture: JSI, Fabric, and TurboModules
The New Architecture removes much of that bottleneck. Based on the linked release notes, React Native now centers on that architecture, with legacy pieces removed from the codebase in the 0.84 release.
A quick way to think about it:
- JSI enables direct C++ calls from JavaScript without the old JSON bridge overhead.
- Fabric is the renderer, with a shared C++ core and support for synchronous layout reads.
- TurboModules load native modules on demand instead of initializing everything at startup.
Taken together, these changes make the runtime easier to reason about when you're dealing with startup time, animation smoothness, or native integrations.
JSI (JavaScript Interface) replaces the async bridge with direct, synchronous C++ calls. JavaScript can hold references to C++ objects and invoke methods without serialization costs. The architecture docs illustrate the throughput difference: VisionCamera uses JSI to process camera frames at roughly 2 GB of data per second, something the old bridge could not handle.
// New Architecture: method bound directly from C++ into the JS runtime
runtime.global().setProperty(runtime, "setTimeout", createTimer);No bridge initialization. No JSON serialization. Complex types like databases, images, and audio samples can now be passed directly.
Fabric renderer is the new renderer, implemented in C++ with a shared core across platforms. It stores the view hierarchy in immutable tree structures, enabling thread-safe processing and multi-priority rendering. Layout information can be read synchronously across threads, which helps avoid the layout-jump issues that affected the old async renderer. Fabric aligns with React 18's concurrent features: Suspense for data fetching, Transitions, and automatic batching.
TurboModules intro covers native modules that lazy-load on demand rather than initializing everything at startup. The original architecture announcement states that modules are "loaded in memory only when they're effectively needed rather than at startup," reducing launch time and helping keep it low as apps grow in complexity. Because TurboModules are built on JSI, native calls bypass the bridge entirely and can return values synchronously.
The threading model now uses two primary threads: the UI thread, the only thread that can manipulate host views, and the JavaScript thread, where React's render phase and layout execute. Thread safety is enforced through C++ const correctness, so every update creates new objects rather than mutating existing ones.
Concrete results from the 0.76 benchmarks: Android app size dropped by approximately 3.8 MB, about 20%, and median startup time improved by about 15ms, or roughly 8%, compared to the legacy architecture.
In practice, this means you can keep the React programming model, iterate quickly with hot reload, and still ship apps that use native UI components.
Key Benefits of React Native
The framework's advantage lies in shared codebases, smaller teams, and feedback loops measured in seconds instead of minutes.
Cross-Platform Code Reuse
One codebase, multiple platforms. Development teams commonly reuse much of their code across iOS, Android, and web, with the shared language, tooling, and component model making high reuse rates achievable. DataCamp reuse documented 90% component reuse when porting a mobile app to web using React Native for Web, covering UI components, Redux action creators, reducers, and the networking layer.
Exact percentages vary by project architecture and platform targets, but the pattern holds: you write business logic, state management, and most UI components once. Platform-specific divergence lives in isolated modules, and most differences resolve with a single conditional:
import { Platform, StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
header: {
paddingTop: Platform.OS === 'ios' ? 60 : 40, // one conditional, two platforms
},
});By localizing divergence, you reduce cognitive load and keep pull requests focused. Feature parity becomes more realistic instead of turning into a recurring budgeting problem.
Leverage Existing JavaScript Talent
If your company already invests in web development, React Native taps that talent pool immediately. The mental model, components, props, state, and hooks, stays intact. The 2025 survey reports that JavaScript is widely used by developers, and TypeScript is also broadly adopted.
The learning curve is minimal:
// React web
export function Button({ label }) {
return <button>{label}</button>;
}
// React Native
import { TouchableOpacity, Text } from 'react-native';
export function Button({ label }) {
return (
<TouchableOpacity>
<Text>{label}</Text>
</TouchableOpacity>
);
}Same component boundary, same data flow, different render target. The framework embraces the JavaScript ecosystem you already know. New teammates ramp up faster, and the codebase usually feels familiar rather than foreign.
Hot Reloading and Fast Iteration
Traditional mobile development follows a cycle: change code, compile, install, navigate to screen, repeat.
React Native's hot reloading cuts that loop to seconds by injecting code changes into a running app while preserving state. Adjust a flexbox rule, hit save, and watch the UI update immediately.
That instant feedback works with familiar tooling. You debug async storage calls in Chrome DevTools, profile performance in DevTools, and set breakpoints in VS Code. You do not need to juggle Xcode and Android Studio unless you're deep inside a native module.
When stakeholders request a color change during a demo, you can edit the style and reload instantly. Faster feedback means more room to experiment, which usually helps teams ship better apps on a tighter schedule.
Getting Started with React Native
Two paths exist for new projects. Both converge on the same New Architecture under the hood, so the choice comes down to how much native tooling you want to manage upfront.
The Expo Workflow (Recommended)
Expo is now the recommended workflow for building React Native apps. The React Native docs state that "most developers benefit from using a React Native Framework like Expo," which provides file-based routing, high-quality universal libraries, and the ability to write plugins that modify native code without having to manage native files.
Get a project running on a real device in minutes:
npx create-expo-app@latest
npx expo startScan the QR code with Expo Go on your phone and you're previewing live. No Xcode or Android Studio required to start. Expo Go works well for learning and prototyping, though production projects should graduate to dev builds that support custom native modules.
Expo Router adds file-based routing. Drop a file in the app directory and it automatically becomes a route, similar to how Next.js handles web routing. Deep linking, async routes for lazy bundling, and cross-platform web support come pre-configured in the default template.
The Bare React Native CLI
For teams that know they'll need deep native integration from day one, the bare CLI provides full control:
npx @react-native-community/cli@latest init AwesomeProjectThis path requires Xcode and Android Studio installed, and you manage the ios and android directories yourself. It's the right choice when your project has custom native module requirements or constraints that framework limits do not serve well.
A middle ground exists: Expo's bare-minimum template generates native directories while keeping Expo tooling available. Existing React Native apps can also adopt Expo incrementally without removing native directories.
Best Use Cases for React Native
The framework excels when you need native-quality performance without maintaining separate codebases. These scenarios deliver the highest return on your investment.
Content-Driven and E-Commerce Apps
Social feeds, news readers, and retail catalogs spend most of their time fetching and rendering lists, tasks React Native handles through the same native scrolling components iOS and Android provide. Shopify story describes how Shopify rebuilt its entire merchant mobile suite with the framework while shipping features to both platforms simultaneously.
Startup MVPs and Rapid Prototyping
Companies racing toward market validation care most about speed. React Native lets you write JavaScript once, adjust platform-specific edges, and reach both app stores earlier. Hot reload accelerates the feedback loop during user testing, and that development velocity can matter when you're trying to capture a market window.
Content-Managed Mobile Apps
Apps requiring dynamic content find the framework especially compelling when paired with a CMS guide like Strapi. You can push content updates without app store reviews, keeping your app fresh while the native shell handles push notifications, gesture handling, and offline caching:
import { useEffect, useState } from 'react';
import { View, Text, FlatList } from 'react-native';
export default function ArticlesScreen() {
const [articles, setArticles] = useState([]);
useEffect(() => {
fetch('https://my-strapi-instance.com/api/articles?populate=*')
.then(res => res.json())
.then(json => setArticles(json.data));
}, []);
return (
<FlatList
data={articles}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => (
<View style={{ padding: 16 }}>
<Text style={{ fontSize: 18 }}>{item.attributes.title}</Text>
</View>
)}
/>
);
}React's component model maps cleanly from browser to mobile, keeping your design system unified. Strapi's REST and GraphQL APIs integrate directly with React Native's fetch layer, and the admin panel lets content teams publish updates independently without developer involvement. Combined with Strapi's i18n support, you can manage multilingual mobile content from a single backend.
When to Consider Native Instead
Despite React Native's broad coverage, specific technical constraints make native development the better choice in certain scenarios:
- Graphics-intensive applications: 3D games and AR experiences require real-time GPU rendering where even JSI-level latency can cause visible frame drops.
- High-frequency sensor processing: Applications relying on continuous sensor data at tight timing thresholds benefit from direct platform access.
- Bleeding-edge hardware APIs on launch day: Projects requiring immediate access to the latest device APIs on release day may need native code to ship on time.
- Teams with deep existing native expertise: Organizations with established Swift or Kotlin teams may find introducing a JavaScript layer adds coordination overhead without proportional benefit.
The New Architecture narrows these gaps significantly. JSI makes it practical to extract performance-critical subsystems into native C++ or Kotlin and Swift modules while keeping the rest of the app cross-platform. This hybrid pattern has replaced the all-or-nothing choice that characterized earlier framework limitations. Companies now extract specific subsystems to native rather than abandoning the framework entirely.
Evaluate your requirements honestly: How critical is sustained 60fps rendering under GPU load? How quickly do you need access to new platform APIs? When these factors dominate, consider pure native development or a hybrid approach with performance-critical paths in native code.
The React Native Ecosystem
The tooling and community surrounding the framework have matured substantially, creating a cohesive developer experience.
A few parts of the ecosystem matter most when you're evaluating day-to-day workflow:
- Hermes V1 became the default engine in React Native 0.84. Early benchmarks from the 0.82 release, tested against the Expensify app, showed 7.6% faster Total TTI on a low-end Android device and 9% faster bundle load time on iOS, though improvements depend on app specifics.
- Expo Router provides file-based navigation for React Native. Drop a file in the
appdirectory and it becomes a route, with deep linking, async routes, and web support included. - React Native DevTools shipped Network and Performance panels in the 0.83 release, replacing the previous Flipper-based debugging workflow. You can now record network calls, inspect JavaScript execution timelines, and profile React performance tracks in a single tool.
- Reanimated handles gesture-driven animations, and Gesture Handler provides the touch handling layer. Both reflect the ecosystem's consolidation around JSI and Fabric primitives.
The broader community remains active: 126,000+ GitHub stars and official community channels across Discord, Slack and Reddit listed at the community page.
Build Once, Deploy Everywhere
React Native helps you avoid the build-it-twice cycle by letting you target iOS and Android from one JavaScript codebase that renders genuine native widgets on each platform. You still need to evaluate the tradeoffs, but you gain hot reloading, a component-based architecture, and an ecosystem built around the newer C++ rendering pipeline.
If you're evaluating the framework, start practical: install Expo, spin up a hello-world project, and wire it up to a headless CMS like Strapi to see real data render on a physical device. Hands-on experience will tell you more than any benchmark, and you can get there quickly.
Get Started in Minutes
npx create-strapi-app@latest in your terminal and follow our Quick Start Guide to build your first Strapi project.