Skip to main content
Mobile & Ecosystems progress
advancedPage 3 of 10

React Native

How React Native maps your React/TS skills to real native apps, Expo, the new architecture, native modules, and where it fits vs Flutter and native.

React Native

In one line: React Native lets you build genuinely native iOS and Android apps using React and TypeScript — the same component model and language you already know — by rendering to real native UI widgets rather than a webview, which is why it's the default mobile path for teams that already live in the React ecosystem.

In plain English

If you know React, React Native is most of the way to a mobile app. You write components with the same mental model — useState, props, JSX — but instead of <div> and <p> you use <View> and <Text>, and those map to actual native UI controls on the phone (not a web page in a wrapper). The result is a real app in the App Store that feels native, built largely with skills you already have. Meta builds parts of Facebook and Instagram with it; Shopify, Discord, and many others ship it. The headline benefit is leverage: one React/TS team can produce iOS, Android, and (with React Native for Web) share logic with your website, instead of hiring separate Swift and Kotlin specialists. The tradeoffs are real but manageable — occasional need to touch native code, and keeping up with a fast-moving framework — and for most product apps they're well worth the team-skill reuse.

How it works (and why it's not a webview)

This is the key thing to understand and the most common misconception. React Native does not render your UI in a browser/webview. Your React components describe the UI; React Native translates them into the platform's actual native views (UIView on iOS, android.view on Android). Your JavaScript logic runs in a JS engine and communicates with the native side. So the buttons, lists, and text are real native widgets — they scroll, animate, and feel native because they are native.

// A React Native component — same React you know, native primitives instead of DOM.
import { View, Text, Pressable, StyleSheet } from "react-native";
import { useState } from "react";

export function Counter() {
const [count, setCount] = useState(0);
return (
<View style={styles.container}>
<Text style={styles.label}>Count: {count}</Text>
<Pressable style={styles.button} onPress={() => setCount((c) => c + 1)}>
<Text style={styles.buttonText}>Increment</Text>
</Pressable>
</View>
);
}

// Styling is JS objects (Flexbox by default), not CSS files.
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: "center", alignItems: "center" },
label: { fontSize: 24, marginBottom: 16 },
button: { backgroundColor: "#2563eb", paddingHorizontal: 20, paddingVertical: 12, borderRadius: 8 },
buttonText: { color: "white", fontWeight: "600" },
});

The differences from web React are surfaces, not fundamentals: native primitives instead of HTML, Flexbox-in-JS instead of CSS, and platform APIs (camera, geolocation) via libraries instead of browser APIs. The component model, hooks, state, and data-fetching patterns transfer directly.

Expo: the way to start (and increasingly, to stay)

Expo is to React Native roughly what Next.js is to React — a batteries-included framework and toolchain that removes most of the painful setup. It gives you a managed build pipeline, a huge library of pre-built native modules (camera, notifications, secure storage) you can use without writing native code, over-the-air JS updates, and EAS (Expo Application Services) for cloud builds and store submission. The modern advice is unambiguous: start with Expo. The old reasons to "eject" to bare React Native have largely evaporated as Expo matured to support custom native code via config plugins and development builds. Starting bare today is usually self-inflicted pain.

# A new RN app, running on a device, in two commands:
npx create-expo-app@latest my-app
cd my-app && npx expo start # scan the QR code with the Expo Go app to see it live

Native modules and the bridge

When you need a device capability no library covers, or you must integrate a vendor's native SDK, you write a native module — a small piece of Swift/Kotlin exposed to your JS. You don't escape native code entirely; you minimize it. The communication between JS and native historically went over an asynchronous "bridge," which could bottleneck on heavy interactions (e.g. high-frequency gestures or large data transfers). React Native's New Architecture (JSI / Fabric / TurboModules), now the default, replaces that bridge with a faster, synchronous interface — substantially improving performance for exactly those heavy cases and closing much of the historical gap with Flutter and native.

Highlight: React Native's real superpower is skill and code reuse, not raw performance

Be honest about why you'd pick React Native. It is not (usually) because it's the most performant option — native is, and Flutter's rendering is very consistent. You pick React Native because of leverage: your existing React/TypeScript developers become mobile developers, you maintain one codebase for two platforms, you can share business logic, types, and validation with your web app, and your hiring pool is "React developers" (huge) rather than "Swift + Kotlin specialists" (smaller, pricier, ×2). For a product company already building a React web app, that compounding reuse — one team, one language, shared code, one mental model from web to mobile — is frequently the deciding factor, and it's a genuinely strong one. Choose RN when ecosystem fit and team leverage matter more than squeezing out the last 10% of native performance, which is most product apps.

When React Native fits — and when it doesn't

Good fit: product apps, content apps, social, commerce, dashboards, most CRUD-shaped mobile apps — especially when your team and/or web app are already React/TS. Weaker fit: graphically intense games, apps doing heavy real-time on-device computation (video/audio processing, AR-centric experiences), or apps that must adopt brand-new OS features the instant they ship — there, native earns its cost. Versus Flutter (next page): both are excellent cross-platform choices; the tilt is largely "does your team already know React/TS (→ RN) or are you starting fresh / want maximum UI consistency (→ Flutter)?"

Common mistakes

Where people commonly trip up
  • Thinking React Native is a webview. It renders real native widgets; performance and feel are native, not web-in-a-wrapper. (That's a different approach, like Capacitor.)
  • Starting with bare React Native instead of Expo. You take on native-toolchain pain that Expo now handles, including custom native code via config plugins. Start with Expo.
  • Expecting 100% code sharing and zero native code. You'll occasionally write a native module or hit platform differences; budget for a little Swift/Kotlin and platform-specific tweaks.
  • Choosing RN for a heavy game or AR-centric app. Those are where native (or a game engine) earns its keep. RN shines for product/CRUD/content apps.
  • Ignoring the framework's pace. React Native moves fast (the New Architecture, library churn); plan for periodic upgrade work rather than set-and-forget.
  • Picking RN vs Flutter on benchmarks alone. For most apps both are plenty fast; decide on team skills and ecosystem fit, which usually points React teams to RN.

Page checkpoint

Checkpoint Quiz

Did React Native stick?

Required

What's next

→ Continue to Flutter — the other major cross-platform contender, with a different philosophy: own the entire rendering pipeline.