OpenAIExpoDec 11, 2025, 5:15 PM

From Web to Native with React

A condensed section focused on the key takeaways first.

Original Post

Quick Digest

Summary

A condensed section focused on the key takeaways first.

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

From Web to Native with React

Key Points

  • React Native uses native primitives (no HTML)
  • Use FlatList/ScrollView for scrollable content; avoid mapping large arrays
  • Expo supplies SDK, tooling and simplifies builds for most apps

Summary

A concise engineer-focused guide for React web developers starting with React Native. Covers the practical platform differences (UI primitives, layout, input, lists), styling rules, performance pitfalls, and why using Expo as a framework significantly reduces friction for building, testing, and shipping production mobile apps.

Key Points

  • Transferable skills: JavaScript/TypeScript and React patterns carry over, but platform APIs and primitives differ.
  • UI primitives: There is no HTML in React Native — use View, Text (all visible text must be wrapped), Image, TextInput, ScrollView, FlatList, Pressable/TouchableOpacity, Switch.
  • Text requirement: Failing to wrap rendered text in a Text component can crash the app.
  • Scrolling & lists: Pages are not scrollable by default. Use ScrollView for simple content and FlatList/SectionList for long lists to avoid performance issues (do not map large arrays directly).
  • Inputs & interactions: TextInput uses onChangeText; Pressable (or TouchableOpacity) replaces web buttons and offers touch-specific behavior.
  • Styling: Styles are inline via the style prop (StyleSheet.create). No global CSS; Flexbox is the default layout with different defaults (column, flexShrink=0, etc.). Consider styling libraries (NativeWind, Styled Components, Tamagui) if you need global themes or cross-platform UI kits.
  • Images: Built-in Image works, but production apps often prefer FastImage or Expo Image for caching and extra formats.
  • Use Expo: Expo provides an SDK (camera, notifications, storage), CLI, build/delivery tooling, OTA updates, and a curated set of libraries — recommended for most new apps unless you need custom native modules.
  • Tooling & libraries: Leverage community libraries but prefer well-maintained, compatible stacks (Expo SDK + community libs) to avoid maintenance overhead.

Practical next steps

  • Start with Expo for prototyping and builds unless you require heavy native customization.
  • Replace naive array.map list rendering with FlatList for any potentially large lists.
  • Centralize shared styles in a theme file and import into components; use a styling library if you need CSS-like ergonomics or design system primitives.
  • Read the official React Native docs for full component and API details and profile app performance early when targeting mobile devices.

Full Translation

Translations

A translation section that keeps the flow of the original article.

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(さまざまなアプローチを比較したもの)をチェックしてください。

From Web to Native with React | Expo | DocsDigest