OpenAIExpo2025/12/11 17:15

From Web to Native with React

要点だけを先に読めるように短く再構成したセクションです。

元記事

Quick Digest

要約

要点だけを先に読めるように短く再構成したセクションです。

openaijamodel: gpt-5-mini-2025-08-07

ReactでWebからネイティブへ — 初めてのReact Native移行ガイド

Key Points

  • Textで必ずラップ
  • FlatListで大量リストを処理
  • Expoを初期選択肢に

Summary

React経験のあるWeb開発者向けに、ReactからReact Nativeへ移行する際の実務的な注意点と推奨フローをまとめました。JavaScript/TypeScriptの再利用が可能ですが、UIプリミティブ、スタイリング、パフォーマンス対策、ネイティブ連携はWebと異なるため、早めに慣れる必要があります。Expoを利用すると必須のネイティブ機能やビルド/配布ツールが揃い、初期開発が大幅に楽になります。

Key Points

  • 移行の利点

    • 多くのロジックはJS/TSで再利用可能。ネイティブの見た目とパフォーマンスはReact Native側で担保される。
    • ExpoはネイティブAPIやビルド・配布・OTAなどのツール群を提供し、フレームワークとして推奨される。
  • UIプリミティブ(Web→Nativeで置き換える必須点)

    • HTMLは使えない:View, Text, Image, ScrollView, FlatList, TextInput, Pressable/Touchableなどを使う。
    • すべてのテキストは必ず<Text>でラップしないとクラッシュする可能性がある。
    • 画像はリモートは{ uri }、ローカルはrequire()で指定。多くはExpo ImageやFastImageを推奨。
  • パフォーマンスとリスト表示

    • 大量リストはmapではなくFlatList/SectionListで仮想化する(遅延レンダリング・差分最適化)。
  • スタイリングの違い

    • グローバルCSSはない。スタイルはstyleプロップで渡す(StyleSheet.createで管理)。
    • Flexbox挙動がWebと異なる(directionがcolumn、flexShrinkやalignContentのデフォルト差分に注意)。
    • 必要ならNativeWind / styled-components / tamaguiなどのライブラリを検討。
  • 入出力とインタラクション

    • TextInputはonChangeTextを使う。ボタン系はPressableやTouchableでタップ挙動を扱う。
    • Switchなどはプラットフォームごとに見た目が変わることを意識する。
  • 実務的な推奨ワークフロー

    • 新規アプリはまずExpoでプロトタイプ→必要ならbare workflowへ移行。
    • 標準のReact Nativeに欠ける機能(通知、カメラ、ファイル等)はExpo SDKや実績あるOSSを選ぶ。
    • ドキュメントと公式コンポーネント一覧を早めに確認し、Platform差分をテストする。
  • まとめ

    • Webの知識は有利だが「そのままコピー」は危険。UIプリミティブ、スタイル、リスト処理、ネイティブAPIの使い方を押さえて移行すると生産性が高い。

Full Translation

翻訳

原文の流れを保ったまま読める翻訳セクションです。

openaijamodel: gpt-5-mini-2025-08-07

ReactでWebからネイティブへ

Development • December 11, 2025 • 30 minutes read • Kadi Kraman • Engineering

すべてのWeb開発者が最初のReact Nativeアプリを作るために知っておくべきこと。

React Nativeは、Reactの経験があるWeb開発者が最初のモバイルアプリを作るのに非常に適した選択肢です。ReactとReact Nativeは多くの類似点がありますが、Webとネイティブをターゲットにする場合には重要な違いも存在します。本記事は、ReactからReact Nativeへ移行する際に開発者がよく犯すミスやよくある疑問点を取り上げ、解説することを目的としています。新しいプラットフォームに踏み出す際の「知らなかった未知」を少しでも明確にし、Webからネイティブへの移行を楽にする手助けになれば幸いです。

なぜReact Nativeを選ぶのか

React開発者がReact Nativeを選ぶべき理由をいくつか挙げます。

  • スキルの移転が容易
    • React Nativeでは、アプリケーションコードのほとんどがJavaScript(多くはTypeScript)で書かれます。つまり、経験のあるReact開発者はWebで慣れているコーディングパターンやライブラリの多くを引き続き使えます。
  • 本当にネイティブ
    • ほとんどのアプリコードをJavaScriptで書くとはいえ、React Nativeアプリは内部では本物のネイティブアプリです。あなたが書いたReactコードは各プラットフォームの実際のネイティブプリミティブにマッピングされます。これはパフォーマンスとネイティブらしさにとって非常に重要です。
  • マルチプラットフォームでのコード共有
    • React Nativeは同じコードベースからiOSとAndroidの両方のネイティブアプリを構築できます。Expo RouterやAPI Routersを使えば、さらにWebやサーバーもターゲットにできます。つまり、プラットフォーム間で大量のコードを共有できる可能性があります。

なぜExpoを選ぶのか

ExpoはReact Nativeフレームワークです — Next.jsがReactフレームワークであるのと似ています。

React Native自体はネイティブiOS/Android上でReactコードを動かすための基礎を提供します。Text、View、TextInputのような基本コンポーネントも含まれています。しかし、ナビゲーション、プッシュ通知、カメラ利用、アプリ起動間のデータ永続化、ストア向けビルドといった、ほとんどのプロダクションアプリが必要とする多くの機能はReact Nativeコアには含まれていません。これは意図的な設計で、すべてのネイティブ機能を最初から露出すると、Metaの小さなReactチームではReact Nativeを維持できなくなるためです。

コアに主要な機能が含まれないため、開発者は常にさまざまなコミュニティライブラリに頼ってきました。リリースからほぼ10年経ち、選択肢は膨大になっています。特に新規プロジェクトの立ち上げ時には、どのライブラリを選び、どれが相互にうまく動くかを判断するのが難しいことがあります。理想的には、よく使われ、よく保守されたツール群がセットになっていて、開発者が毎回選択に悩まなくて済むのが望ましいです。これがまさにExpoが助ける点です。

ExpoはReact Nativeフレームワークであり、React Nativeが提供するものとプロダクションアプリに必要なその他すべての間のギャップを埋めるツールとサービスの集合です。Expo SDKはReact Native用の拡張標準ライブラリであり、コアに含まれない一般的なネイティブAPI(カメラ、ビデオ、通知など)へのアクセスを提供します。Expoは新しいプロジェクトを作成するためのCLI、学習とプロトタイピング用のサンドボックスアプリ、ファイルシステムベースのナビゲーションシステム、ネイティブコードを管理するツール、アプリをストアにビルド・配信する仕組み、OTA(オーバーザエア)アップデートのセットアップ、さらには独自のネイティブモジュールをビルドするための仕組みを提供します。これらに加えて、ほとんどのオープンソースのReact NativeライブラリもExpo SDKと併用できます。

Metaも新規作成アプリに対してExpoのようなReact Nativeフレームワークの使用を公式に推奨しています。その理由は単純です: フレームワークを使うか、あるいは自分でフレームワークを作るかのどちらかであり、自分でフレームワークを作るのは大多数のReact Native開発者にとって賢明な選択ではないからです。

React Native keynote at React Conf 2024

(ここは元記事の見出しとして残します)

ReactとReact NativeのUIプリミティブ

ネイティブのReact NativeコードはReactのコードと見た目が似ていますが、レンダリングの面で明確な違いがあります。以下はWebでのテキスト表示の例です。

export function MyTextComponent() {
  return (
    <div>
      Hello, web!
    </div>
  );
}

同じことをReact Nativeで表示する方法は次の通りです。

import { View, Text } from "react-native";
export function MyTextComponent() {
  return (
    <View>
      <Text>Hello, native!</Text>
    </View>
  );
}

これらの例は、WebのReactとネイティブのReactの非常に重要な違いを示しています: React NativeにはHTMLのプリミティブ(div、input、formなど)が存在しません。代わりに、それらに相当するプリミティブコンポーネントがreact-nativeライブラリからエクスポートされます。したがって、React Nativeでレンダリングするすべてのものは常にコンポーネントでラップされます。内部的にはReact Nativeはプラットフォームごとの実際のネイティブコンポーネントをレンダリングしますし、そのためUIに表示されるすべてのテキストはTextコンポーネントでラップする必要があります。これを怠るとアプリがクラッシュします。

以下はReact Nativeに含まれる主なUIプリミティブの一部です。

  • View

    • Webでの最も近い相当: div
    • ViewはWebのdivに相当し、レイアウトとスタイリングに使用されます。
  • ScrollView

    • Webでの最も近い相当: div
    • Webではページはデフォルトでスクロール可能ですが、ネイティブではそうではありません。ページをスクロール可能にするにはScrollView(またはFlatListやSectionListのような仮想化されたリスト)でラップする必要があります。
  • Text

    • Webでの最も近い相当: p
    • React NativeでレンダリングするすべてのテキストはTextでラップする必要があります。
  • Image

    • Webでの最も近い相当: img

    • 画像コンポーネントはURLからもローカルファイルからも画像をレンダリングできます。APIはWebと少し異なります。例えばURLから画像を読み込むには次のようにします。

      import { Image } from "react-native"; export function MyImage() { return <Image source={{ uri: "https://domain.com/static/my-image.png" }} />; }

    • ローカルファイルからレンダリングするには次のようになります。

      import { Image } from "react-native"; const imageSource = require("../assets/my-image.png"); export function MyImage() { return <Image source={imageSource} />; }

    • 多くのプロダクションアプリは組み込みのImageコンポーネントではなく、FastImageやExpo Imageを使います。これらのライブラリはスタイリング、キャッシング、追加の画像フォーマット対応などの機能を含んでいます。

  • FlatList

    • Webでの最も近い相当: array.map()

    • Webでは配列をmapして長いリストをレンダリングすることが多いですが、ネイティブではパフォーマンス上の理由から避けるべきです。代わりにFlatListを使いましょう。FlatListは仮想化されたリストで、不要なデータのレンダリングを遅延させる、基になるデータが変わらない限りリストを再レンダリングしないなどの最適化が組み込まれています。

      import { Text, FlatList, View } from "react-native"; const posts = [ { id: "1", name: "Post 1" }, { id: "2", name: "Post 2" }, ]; export function MyList() { return ( <FlatList data={posts} renderItem={({ item }) => ( <Text>{item.name}</Text> )} /> ); }

  • TextInput

    • Webでの最も近い相当: <input type="text" />

    • テキスト入力コンポーネントはテキストベースの入力全般に使います。Webのinputと異なり、テキスト(および数値)用に設計されています。TextInputにはonChangeコールバックもありますが、通常は更新されたテキスト文字列を直接返すonChangeTextを使います。

      import { useState } from "react"; import { StyleSheet, TextInput } from "react-native"; export function MyInput() { const [value, setValue] = useState(); return <TextInput value={value} onChangeText={setValue} />; }

  • TouchableOpacity

    • Webでの最も近い相当: button

    • タップに反応する領域を作りたいときは、その領域をTouchableOpacityでラップします。名前の通り、押されたときに自動的にハイライトされ、activeOpacityプロップで強調の度合いを調整できます。

      import { TouchableOpacity, Text } from "react-native"; export function MyButton() { const onPress = () => { console.log("Pressed!"); }; return ( <TouchableOpacity onPress={onPress} activeOpacity={0.8}> <Text>Button Text</Text> </TouchableOpacity> ); }

  • Pressable

    • Webでの相当: <button />
    • TouchableOpacityに似ていますが、Pressableはタッチアクションに対してより高いレベルの制御を提供する後継コンポーネントです。
  • Switch

    • Webでの相当: <input type="checkbox" />

    • Switchは値をtrue/falseで切り替えるトグルコンポーネントです。iOSとAndroidで見た目が異なるプラットフォーム固有の実装の好例です。

      import { Switch } from "react-native"; export function MySwitch() { const [value, setValue] = useState(false); return ( <Switch value={value} onValueChange={(value) => setValue(value)} trackColor={{ true: "pink" }} /> ); }

上記はReact Nativeのコアコンポーネントの抜粋です。完全な一覧や詳細は公式のReact Native docsを参照してください。

React Nativeのスタイリング

WebでのCSSの書き方を知っていれば、React Nativeのスタイリングは比較的簡単に学べます。多くのCSSプロパティがサポートされていますが、いくつか違いがあります。

グローバルスタイルはない

すべてのスタイルはインラインでコンポーネントにstyleプロップとして渡されます。スタイリングライブラリを使わない限り、グローバルスタイルを定義することはできません。コンポーネント間でスタイルを共有するには、例えばテーマファイルを作成して各ファイルでインポートするといった方法があります。

import { View, Text } from "react-native";
export function MyComponent() {
  return (
    <View style={styles.container}>
      <Text style={styles.greeting}>Set Reminder</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: "#fff", padding: 24 },
  greeting: { fontSize: 24 },
});

Flexbox — 少しの違いあり

React Nativeでは配置にFlexboxを使います。Webと近い挙動ですが、いくつかの違いがあります:

  • すべての要素はデフォルトで display: flex
  • flexDirection のデフォルトは column(Webは row)
  • alignContent のデフォルトは flex-start(Webは stretch)
  • flexShrink のデフォルトは 0(Webは 1)
  • flexプロパティは単一の数値のみサポート

スタイリングライブラリ

組み込みのインラインスタイルは十分な場合が多いですが、代替のスタイリング体験を望む開発者向けのライブラリもあります。人気のあるライブラリには次のようなものがあります:

  • NativeWind — React NativeでのTailwindスタイル
  • Unistyles — より包括的なStyleSheet
  • Styled Components — CSS構文でスタイル記述
  • Tamagui — クロスプラットフォームのスタイリングとUIキット

もしさらに深掘りしたければ、以前に実施したLiveStream(さまざまなアプローチを比較したもの)をチェックしてください。