第3章 ReactとReact Nativeの違いと共通点
コンポーネント指向やHooksがそのまま通用する一方で、DOM・CSS・ブラウザAPIがない環境で何を学び直すことになるかがつかめます。
React開発の経験があるエンジニアにとって、React Nativeへの入り口で気になるのは「どこまでが同じで、どこからが違うのか」という点だと思います。本章では両者の差分を整理し、Webの知識がそのまま使える領域と、学び直しが必要な領域を分けて見ていきます。
共通する考え方
まず、Reactで身につけた発想のほとんどはそのまま通用します。
コンポーネント指向
UIを関数コンポーネントに分割し、propsで値を渡し、必要に応じてstateを持たせる、という基本構造は同じです。
type GreetingProps = {
name: string;
};
function Greeting({ name }: GreetingProps) {
return <Text>こんにちは、{name}さん</Text>;
}
返すのが<div>か<View>かの違いはありますが、設計の発想は変わりません。
Hooks
useState、useEffect、useMemo、useCallback、useReducer、useContext、カスタムフック ― これらはすべてReact Nativeでも同じように使えます。React 19で追加されたuse、useActionState、useOptimistic、React 19.2のuseEffectEventなども同様です。
「Hooksの使い方をWeb側で身につけている」というだけで、React Native側の学習はかなり省けます。
状態管理ライブラリ
Zustand、Jotai、Redux Toolkitなど、Web側で使われている状態管理ライブラリは、おおむねReact Nativeでもそのまま動きます。Reactのコンポーネントツリーに対して動くライブラリであれば、ランタイムが違ってもインターフェースは同じだからです。
データフェッチ
TanStack QueryやSWRといったデータフェッチライブラリも、そのまま使えます。fetch APIもReact Nativeに標準で用意されています(厳密にはWebのfetchと完全に同じではないものの、基本的な使い方の範囲では差を意識せずに済みます)。
TypeScript
型定義の書き方、tsconfigの方針、ESLintの考え方、Prettierの使い方など、コードの書き心地に関する部分はWebとほぼ変わりません。
決定的に違う点
ここからが「学び直し」が必要な領域です。
DOMがない
最大の違いはこれです。
React NativeにはDOMがありません。document.getElementByIdもdocument.createElementも存在しません。windowオブジェクトも、ブラウザに紐づく機能(window.location、window.history、window.scrollYなど)はそもそも提供されません。
DOMを直接触るタイプのライブラリは、まず動きません。<div>を直接書くこともできず、代わりに<View>、<Text>、<Image>、<TextInput>、<ScrollView>、<FlatList>といったReact Nativeのコアコンポーネントを使います。
| Web | React Native |
|---|---|
<div> |
<View> |
<span> <p> |
<Text> |
<img> |
<Image> |
<input type="text"> <textarea> |
<TextInput> |
<button> |
<Pressable> |
<a> |
<Link> (Expo Router) |
スクロール領域(overflow: auto) |
<ScrollView> |
大量リスト(<ul> + map) |
<FlatList> |
| ノッチを避ける外枠 | <SafeAreaView> |
切り替えコントロール(<input type="checkbox">の見た目違い) |
<Switch> |
| ローディング表示 | <ActivityIndicator> |
| アラート/確認ダイアログ | Alert.alert() |
React Nativeのコアコンポーネントは「意外と少ない」のが特徴で、上記がほぼすべてです。残りはExpo Modulesやサードパーティライブラリで補います。
たとえば、同じ「アバター画像とユーザー名のカード」をWebとReact Nativeで書き比べると、こんな対応関係になります。
// Web (React)
function ProfileCard() {
return (
<div className="card">
<img src="/avatar.png" className="avatar" />
<p className="name">kazutoyo</p>
</div>
);
}
// React Native
function ProfileCard() {
return (
<View style={styles.card}>
<Image source={{ uri: "/avatar.png" }} style={styles.avatar} />
<Text style={styles.name}>kazutoyo</Text>
</View>
);
}
タグ名とstyleの与え方が変わるだけで、JSXの構造はそのままです。詳しい使い方は第6章で扱います。
CSSが使えない
stylesheetやCSS-in-JSライブラリ(CSSベースのもの)、Tailwindの素のクラスなどは、そのままでは動きません。代わりに、JavaScriptオブジェクトとしてスタイルを書くStyleSheet APIを使います。
import { StyleSheet, View, Text } from "react-native";
function Card() {
return (
<View style={styles.card}>
<Text style={styles.title}>タイトル</Text>
</View>
);
}
const styles = StyleSheet.create({
card: {
padding: 16,
borderRadius: 8,
backgroundColor: "#fff",
},
title: {
fontSize: 18,
fontWeight: "bold",
},
});
書き方が違うだけで、考え方はWebのスタイル指定と地続きです。プロパティ名はキャメルケースになり、値は文字列("#fff")か数値(16)で指定します。
ただし、使えるプロパティは「CSSのサブセット」と思っておくのが安全です。grid-template-columnsは今のところ使えません(2026年に向けて、React NativeのレイアウトエンジンYogaへCSS Grid追加が議論されています)。background-imageもありません(画像は<Image>コンポーネントで配置するか、サードパーティのライブラリでサポートされています)。
Tailwindライクなスタイリングが好みであれば、Uniwindという選択肢があります。詳しくは第7章で扱います。
ブラウザAPIがない
localStorage、sessionStorage、IndexedDB、document.cookie、navigator.geolocation、navigator.mediaDevices、Notification、Web Speech API、Service Worker ― これらブラウザに紐づくAPIは、React Nativeには存在しません。
代替として、それぞれの機能はExpoのモジュールが提供しています。
| Web | React Native (Expo) |
|---|---|
localStorage |
AsyncStorage / MMKV |
navigator.geolocation |
expo-location |
navigator.mediaDevices |
expo-camera / expo-image-picker |
Notification |
expo-notifications |
| URLルーティング | Expo Router |
「Webにあるあの機能、モバイルでは何を使う?」という対応関係を覚えていけば、徐々に脳内のマッピングが揃っていきます。
Flexboxのデフォルトが違う
Webではdisplay: flexを指定しなければflexになりませんし、flexにした場合のデフォルトはflex-direction: rowです。

React Nativeでは次のようになっています。
- すべての
<View>は最初からdisplay: flex相当(displayはflex/none/contentsの3値のみでWebほど種類はありません) flex-directionのデフォルトは**column**(縦並び)
これは「縦スクロールが基本のモバイル画面」という前提に最適化された結果です。Webの感覚で組むと「あれ、横に並ばない…」と最初に戸惑うポイントですが、慣れてしまえば縦が基本なほうが楽な場面が多いです。align-itemsのデフォルトがstretchなのはWebと同じです。
横並びにしたい時だけflexDirection: "row"を明示します。
単位が違う(pxではなくdp)
CSSではピクセル単位(px)、emやrem、vw/vhなどさまざまな単位がありますが、React Nativeではスタイルの数値はすべて**dp(密度非依存ピクセル)**として扱われます。単位を書く必要すらありません。
// Web
const style = { padding: "16px", fontSize: "18px" };
// React Native
const style = { padding: 16, fontSize: 18 };
dpはOSが画面密度に応じて実ピクセルに変換してくれるので、解像度の違うデバイスでも見た目のサイズが揃います。
スクロールの扱いが違う
Webでoverflow: autoを指定すれば自動でスクロールしましたが、React Nativeではスクロールしたい領域は明示的に<ScrollView>または<FlatList>で囲む必要があります。
リストが大量になる場面では、仮想化されている<FlatList>を使うのが定番です。Webの<div>に大量の<li>を入れてoverflow: auto、というやり方は、モバイルではメモリやパフォーマンスの観点で破綻するので、最初から仮想化を意識します。
詳しくは第6章で扱います。
(コラム) Webのコンポーネントをそのまま持ち込む ― DOM Components
ここまで「DOMがない」「CSSが使えない」と書いてきましたが、逃げ道もあります。ExpoのDOM Componentsです。
ファイルの先頭に'use dom'と書くと、そのコンポーネントだけがReact DOMとして扱われ、WebView上で描画されます。
// components/rich-editor.tsx
'use dom';
export default function RichEditor() {
// ここでは <div> も CSS も、Web向けライブラリもそのまま使える
return <div style={{ padding: 16 }}>Webの世界</div>;
}
呼び出す側は、普通のコンポーネントとしてimportするだけです。Expo SDK 56以降は@expo/dom-webviewが既定で使われるので追加インストールは不要で、SDK 55以前ではreact-native-webviewを入れておきます。
効いてくるのは、リッチテキストエディタやチャートのように「Web向けの資産をそのまま使いたい」場面です。既存のWebサイトをアプリ化したい場合にも、コンポーネント単位で少しずつネイティブへ移していく、という進め方ができます。
ただし中身はWebViewなので、ネイティブUIではありません。スクロールの感触やパフォーマンスはネイティブの部品に劣りますし、多用すれば結局「WebViewアプリ」に近づいてしまいます。アプリの骨格はコアコンポーネントで組み、どうしてもWeb資産を使いたい部分にだけ差し込む ― という距離感で付き合うのが良いと思います。
実際に組み込んでみた手順と使い勝手はExpoのReact DOM componentsでReact NativeにReact(Web)を組み込むに書いています。
知識マップ ― そのまま使える領域 / 学び直しの領域
| 領域 | そのまま使える | 学び直しが必要 |
|---|---|---|
| コンポーネント設計 | ◎ | |
| Hooks | ◎ | |
| TypeScript | ◎ | |
| 状態管理ライブラリ | ◎ | |
| データフェッチ(TanStack Query等) | ◎ | |
| マークアップタグ | コアコンポーネント | |
| スタイリング | StyleSheet API / Uniwind | |
| ルーティング | Expo Router | |
| 永続化 | AsyncStorage / MMKV | |
| メディア・センサー | Expo Modules各種 | |
| レイアウトの直感(Flex方向、単位) | dp、column起点に頭を切り替え |
「学び直し」と書きましたが、内容自体は数日でなじむレベルです。「Webと違う部分」だけにフォーカスして学習リソースを当てれば、思っているより早く立ち上がれます。
本章のまとめ
- Reactで身につけた発想(コンポーネント、Hooks、状態管理、データフェッチ)はそのまま使える
- DOM、CSS、ブラウザAPIといったWeb固有の道具は使えない
- 代わりにコアコンポーネント、StyleSheet API、Expo Modules、Expo Routerが対応する
- レイアウトはflex columnが起点、単位はdp、スクロールは明示的
次章からは、本書で前提とする開発フレームワークExpoについて見ていきます。