---
title: "16 — Mobile with React Native — One Paradigm, Real Native Components"
uid: mobile-react-native
tags: ["ios", "react", "react-native", "roadmap:react", "mobile", "android"]
excerpt: "React Native doesn't render web DOM — it bridges React's tree to the host platform's real native UI components, so the same component model produces genuinely native iOS and Android screens."
date: 2026-08-13T03:27:43+0000
source: https://www.aveshina.my.id/en/blog/mobile-react-native
---

"React running inside a webview" was my React Native misunderstanding, and it missed the bridge entirely. The model that corrected it: **React Native doesn't render web DOM. It uses React's component model and reconciliation, but the host platform is the device's real native UI toolkit, not a browser.** [1][2] The same tree-diffing, hooks, and composition I use on the web produce genuinely native iOS and Android screens, because the bridge translates React's render tree into native view calls.

## The key difference from web React

On the web, React renders to DOM elements — <div>, <span>, <button>. In React Native, there is no DOM. React renders to **native primitives**: View, Text, Image, ScrollView. These map, under the hood, to UIView on iOS and android.view.View on Android — the actual platform widgets. The implications:

- **No HTML, no CSS.** There's no <div>; I use <View>. There's no CSS; layout is done with a subset of Flexbox via the style prop. The way of thinking is "Flexbox everywhere," which is a real adjustment from the cascade.
- **Real native components.** A <Text> is a native label, a <ScrollView> is a native scroll container. Animations, gestures, and accessibility use the platform's own implementations, not polyfills.
- **The bridge.** React logic runs in a JavaScript thread; the native UI runs on the platform's main thread. The bridge shuttles updates between them. (The newer architecture — Fabric/New Architecture — reduces this overhead, but the conceptual split remains.)

```
// React Native — no DOM, native primitives instead
import { View, Text, Pressable, StyleSheet } from 'react-native';

function Card({ title, onPress }) {
  return (
    <Pressable style={styles.card} onPress={onPress}>
      <Text style={styles.title}>{title}</Text>
    </Pressable>
  );
}

const styles = StyleSheet.create({
  card: { padding: 16, backgroundColor: '#fff', borderRadius: 8 },
  title: { fontSize: 16, fontWeight: '600' },
});
```

The component shape is familiar — props, composition, hooks all carry over — but the primitives and styling model are different. That's the transfer cost.

## What carries over from web React

This is the real value proposition. Because React Native is React, the parts of the React way of thinking I built on the web transfer directly [1][2]:

- **Components, props, state.** The functional-component-and-props model is identical.
- **Hooks.** useState, useEffect, useReducer, custom hooks — all work the same. (Effects reach native APIs instead of browser APIs, but the shape is unchanged.)
- **Reconciliation and the tree model.** The same render-and-commit cycle drives updates.
- **State management and data fetching.** Zustand, TanStack Query, Apollo — these are platform-agnostic and work in React Native unchanged.

What does **not** carry over: anything DOM-specific. Routing uses a different library (React Navigation, not React Router). Styling is the Flexbox-via-style-prop model, not CSS/Tailwind. Form libraries differ. The web frontend tooling (CSS-in-JS, headless UI libraries) doesn't apply. So the transfer is the React core, not the web ecosystem around it.

```figure
<svg viewBox="0 0 740 300" xmlns="http://www.w3.org/2000/svg" class="my-6 w-full max-w-2xl" role="img" aria-label="React Native architecture. A React component tree at the top uses the same model as web React (components, props, hooks, reconciliation). A bridge connects it to two native hosts: iOS rendering UIView-based screens, Android rendering android.view.View-based screens. Both produce genuinely native UI, not webviews.">
  <defs>
    <marker id="narrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
      <path d="M0,0 L10,5 L0,10 z" fill="#64748b"/>
    </marker>
  </defs>
  <g font-family="ui-sans-serif, system-ui, sans-serif" text-rendering="geometricPrecision">
    <!-- React tree (shared) -->
    <rect x="240" y="24" width="260" height="60" rx="10" fill="#e0e7ff" stroke="#6366f1" stroke-width="1.5"/>
    <text x="370" y="48" font-size="13" font-weight="700" fill="#1e1b4b" text-anchor="middle">React component tree</text>
    <text x="370" y="68" font-size="10" fill="#1e1b4b" text-anchor="middle">components · props · hooks · reconciliation</text>

    <!-- bridge -->
    <rect x="290" y="110" width="160" height="40" rx="8" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.5"/>
    <text x="370" y="135" font-size="11" font-weight="700" fill="#422006" text-anchor="middle">React Native bridge</text>
    <path d="M370,84 L370,108" stroke="#64748b" stroke-width="1.5" marker-end="url(#narrow)"/>

    <!-- iOS host -->
    <rect x="80" y="180" width="240" height="90" rx="10" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
    <text x="200" y="206" font-size="12" font-weight="700" fill="#052e16" text-anchor="middle">iOS</text>
    <text x="200" y="228" font-size="10.5" fill="#052e16" text-anchor="middle">&lt;View&gt; → UIView</text>
    <text x="200" y="246" font-size="10.5" fill="#052e16" text-anchor="middle">&lt;Text&gt; → UILabel</text>
    <text x="200" y="264" font-size="9.5" fill="#64748b" text-anchor="middle" font-style="italic">native, not webview</text>
    <path d="M320,150 C260,170 220,175 200,178" fill="none" stroke="#64748b" stroke-width="1.5" marker-end="url(#narrow)"/>

    <!-- Android host -->
    <rect x="420" y="180" width="240" height="90" rx="10" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
    <text x="540" y="206" font-size="12" font-weight="700" fill="#052e16" text-anchor="middle">Android</text>
    <text x="540" y="228" font-size="10.5" fill="#052e16" text-anchor="middle">&lt;View&gt; → android.view.View</text>
    <text x="540" y="246" font-size="10.5" fill="#052e16" text-anchor="middle">&lt;Text&gt; → android.widget.TextView</text>
    <text x="540" y="264" font-size="9.5" fill="#64748b" text-anchor="middle" font-style="italic">native, not webview</text>
    <path d="M420,150 C480,170 520,175 540,178" fill="none" stroke="#64748b" stroke-width="1.5" marker-end="url(#narrow)"/>
  </g>
</svg>
```

## When React Native is the right call

The decision is rarely "native vs web" in the abstract — it's about the team and the target. React Native's pitch is **one paradigm (and often one codebase) across iOS and Android**, with the React knowledge a web team already has. For a team that's strong in React and needs both platforms, that's a large productivity win — write the app once, ship to both stores, share business logic and state management with a potential web version.

The cases where it's not the right call: when an app needs deep platform-specific integration (heavy AR, complex camera pipelines, bleeding-edge platform APIs), the bridge can become a bottleneck, and going fully native (Swift/Kotlin) gives more control. For most product apps — lists, forms, navigation, media — React Native covers the ground well, and the gap to fully-native has narrowed sharply with the New Architecture.

## How I use this

React Native is my answer when the target is genuinely mobile-first and a single team needs to cover both iOS and Android — the React way of thinking transfer is real, and the productivity of one codebase is hard to beat for typical product apps. The cost I budget for: re-learning the primitives (View/Text instead of div/span), the Flexbox-only styling model (no Tailwind, no cascade), and a separate routing library (React Navigation). The React core — components, hooks, reconciliation, state management, data fetching — carries over intact, which is why a web React dev can become productive in React Native in days rather than weeks. For web-only targets, none of this applies; React Native is specifically the mobile answer, not a general-purpose one.

## References

[1] Meta, "React Native — learn once, write anywhere," reactnative.dev, 2024. [Online]. Available: [https://reactnative.dev/](https://reactnative.dev/)

[2] Meta, "React Native — getting started," reactnative.dev, 2024. [Online]. Available: [https://reactnative.dev/docs/getting-started](https://reactnative.dev/docs/getting-started)

[3] freeCodeCamp, "React Native course for beginners," YouTube, 2024. [Video]. Available: [https://www.youtube.com/watch?v=ZBCUegTZF7M](https://www.youtube.com/watch?v=ZBCUegTZF7M)

```quiz
Q: React Native renders to:
- a webview running a normal React DOM app
- real native UI components (UIView on iOS, android.view.View on Android), via a bridge
- PDF documents
correct: 1
explain: React Native uses React's component model and reconciliation but the host platform is the device's native UI toolkit, not a browser DOM. The bridge translates the React tree into native view calls.

Q: Which of these carries over from web React to React Native unchanged?
- useState, useEffect, custom hooks, and the component/props model
- <div>, <span>, and CSS classes
- Tailwind utility classes and the CSS cascade
correct: 0
explain: The React core (components, props, hooks, reconciliation, state management, data fetching) transfers. DOM elements, CSS, Tailwind, and web routing do not — those are web-specific.

Q: In React Native, styling is done via:
- a subset of Flexbox through the style prop and StyleSheet — there is no CSS or cascade
- the same Tailwind classes as the web
- inline HTML style attributes
correct: 0
explain: There's no DOM and no CSS. Layout uses a Flexbox subset applied through the style prop and StyleSheet.create(). The model is "Flexbox everywhere," with no cascade.

Q: A good case for choosing React Native over fully native (Swift/Kotlin) is:
- a React-strong team needing both iOS and Android for a typical product app, sharing one codebase
- an app needing deep AR or complex camera pipelines with bleeding-edge platform APIs
- a website
correct: 0
explain: For typical product apps (lists, forms, navigation, media), React Native's one-paradigm-both-platforms productivity wins. Deep platform-specific needs (heavy AR, advanced camera) can make fully native the better call.

Q: Routing in a React Native app is typically handled by:
- React Router (same as web)
- React Navigation, a separate library built for mobile navigation patterns
- the URL bar of a browser
correct: 1
explain: There's no browser URL bar on mobile. React Navigation is the standard library for mobile navigation (stacks, tabs, drawers), separate from web-oriented React Router.
```
