ReactでWebからNativeへ
開発 • 2025年12月11日 • 30分で読める
Kadi Kraman Engineering
Webデベロッパーが初めてのReact Nativeアプリケーションを構築するために知っておくべきすべてのこと。
React Nativeは、React経験を持つWebデベロッパーが初めてのモバイルアプリを作成する際の優れた選択肢です。ReactとReact Nativeは多くの類似点を共有していますが、WebプラットフォームとNativeプラットフォームをターゲットにする際には重要な違いが存在します。このブログでは、ReactからReact Nativeに移行する際にデベロッパーが通常遭遇する最も一般的な間違いや疑問を強調し、対処することを目的としています。これが全く新しいプラットフォームに挑戦する際の「知らない未知」を明確にし、WebからNativeへの旅路を楽にすることを願っています!
React Nativeを選ぶ理由
Reactデベロッパーを待ち受ける巧妙な落とし穴に対処する前に、React Nativeを選ぶべき理由をいくつか見てみましょう:
転用可能なスキル
React Nativeでは、アプリケーションコードのほぼすべてがJavaScript(より多くの場合TypeScript)で書かれます。これは、経験豊富なReactデベロッパーとして、Webで既に慣れ親しんでいる多くの同じコーディングパターンやライブラリを引き続き使用できることを意味します。
真のNative
アプリケーションコードの大部分をJavaScriptで書いているにも関わらず、React Nativeアプリは内部では真のNativeアプリです。書いたReactコードは、各プラットフォームの実際のNativeプリミティブにマッピングされます。これは、パフォーマンスとアプリのNativeな外観と操作感の両方にとって非常に重要です。
マルチプラットフォームコード共有
React Nativeでは、同じコードベースからNative iOSアプリとNative Androidアプリの両方を構築できます。Expo RouterとAPI Routersを使用すれば、WebとServerもターゲットにできます。これは、プラットフォーム間で膨大な量のコードを共有できることを意味します。
Expoを選ぶ理由
ExpoはReact Native Frameworkです - Next.jsがReact Frameworkであるのと同様です。
React Nativeが標準で提供するのは、Native iOSとAndroidプラットフォームでReactコードを実行する能力です。React NativeはText、View、TextInputなどの最も基本的なコンポーネントも付属しています。しかし、ほぼすべてのプロダクションアプリが必要とする膨大な機能が、実際にはReact Nativeに含まれていません:ナビゲーション、プッシュ通知の送信、電話のカメラの使用、アプリ起動間でのデータ永続化、さらにはストアリリース用のアプリ構築などです。
これは設計によるもので、すべてのNative機能を標準で公開すると、MetaのReactチームにとってReact Nativeが保守不可能になるからです。
コア機能が含まれていないため、React Nativeデベロッパーは常に様々なコミュニティライブラリに依存する必要があり、現在 - ほぼ10年経った今 - 選択できるコミュニティライブラリは膨大な数に上ります。これは、特に新しいプロジェクトの開始時に、どのライブラリを使用し、どれが一緒にうまく動作するかについて十分な情報に基づいた決定を下すための知識がない場合、非常に圧倒的になる可能性があります。
理想的には、一般的に使用され、よく保守されたツールのセットを一緒に持ち、選択する必要がないようにしたいものです。これがまさにExpoが支援することです。
ExpoはReact Native Frameworkです:React Nativeが付属するものと、プロダクション対応アプリを構築するために必要なその他すべてとの間のギャップを埋めるツールとサービスのコレクションです。
Expo SDKは、React Native用の拡張標準ライブラリで、コアに含まれていない一般的に使用されるNative API(カメラ、ビデオ、通知など)へのアクセスを提供します。Expoは新しいプロジェクトを作成するためのCLI、学習とプロトタイピング用のサンドボックスアプリ、ファイルシステムベースのナビゲーションシステムを提供し、Nativeコードを管理し、アプリをアプリストアに構築・配信し、Over The Airアップデートを設定し、さらには独自のNativeモジュールを構築するためのツールもあります。
これに加えて、Expo SDKに加えて他のほとんどのオープンソースReact Nativeライブラリも使用できます。
Metaも、新しく作成されるアプリにはExpoのようなReact Native Frameworkを使用することを公式に推奨しています。この提案の理由は単純明快です:フレームワークを使用するか...独自のフレームワークを構築するかのどちらかです。そして独自のフレームワークを構築することは、React Nativeデベロッパーの大多数にとって賢明な選択肢ではありません。
React Conf 2024でのReact Nativeキーノート
ReactとReact NativeのUIプリミティブ
Native 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とNative Reactの非常に重要な違いを強調しています:React NativeにはHTMLプリミティブ(div、input、formなど)がありません。代わりに、同等のプリミティブコンポーネントがreact-nativeライブラリからエクスポートされます。したがって、React Nativeでレンダリングするすべてのものは常にコンポーネントでラップされます。内部的には、React Nativeは各プラットフォーム用の実際のNativeコンポーネントをレンダリングし、同じ理由で、UIに表示されるすべてのテキストはTextコンポーネントでラップする必要があります。これを怠ると、アプリがクラッシュします。
React Nativeに含まれる主要なUIプリミティブの一部は次のとおりです:
View
最も近いWeb相当品:div
Viewは、WebのdivのReact Native相当品であり、同じ方法で使用されます:レイアウトとスタイリング用です。
ScrollView
最も近いWeb相当品:div
Webでは、ページはデフォルトでスクロール可能です。Nativeではそうではありません。ページをスクロール可能にするには、ScrollView(またはFlatListやSectionListなどの他の仮想化リスト)でラップする必要があります。
Text
最も近いWeb相当品:p
React Nativeでレンダリングされるすべてのテキストは、Textでラップする必要があります。
Image
最も近いWeb相当品:img
Imageコンポーネントを使用すると、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} />;
}
ほとんどのプロダクションアプリは、React Nativeの組み込みImageコンポーネントを使用せず、代わりにFastImageまたはExpo Imageを使用することに注意してください。これらのライブラリには、スタイリング、キャッシング、追加の画像フォーマットサポートに関連する追加機能が含まれているためです。
FlatList
最も近いWeb相当品:array.map()
多くのWebUIは、大きなフルスクリーンアイテムのリストのレンダリングに依存しています - Instagramのタイムラインやメールボックスのメールリストを考えてみてください。Webでは配列をマッピングしてこれらをレンダリングするかもしれませんが、パフォーマンス上の理由からNativeプラットフォームでは避けるべきです。代わりに、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" />
名前が示すように、TextInputコンポーネントはテキストベースの入力に使用できます。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コンポーネントはボタンを作成するために使用されます。TouchableOpacityの後継であり、タッチアクションに対してより高いレベルの制御を提供します。
Switch
Web相当品:<input type="checkbox" />
Switchは、値をtrueまたはfalseに切り替えることができるトグルコンポーネントです。プラットフォーム固有の実装により、iOSとAndroidで異なって見えるUI要素の優れた例です。
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ドキュメントを参照してください。
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(rowの代わりに)
alignContentはデフォルトでflex-start(stretchの代わりに)
flexShrinkはデフォルトで0(1の代わりに)
flexパラメータは単一の数値のみをサポート
スタイリングライブラリ
組み込みのインラインスタイルはReact Nativeアプリのスタイリングに適した選択肢であり、多くのReact Nativeアプリはスタイリングライブラリを全く使用していませんが、代替のスタイリング体験を望むデベロッパー向けのライブラリが利用可能です。
React Native用のより人気のあるスタイリングライブラリには以下があります:
- NativeWind - React NativeでのTailwindスタイル用
- Unistyles - より包括的なStyleSheet
- Styled Components - CSS構文でスタイルを書くため
- Tamagui - クロスプラットフォームスタイリングとUIキット用
より深く掘り下げたい場合は、以前に実施した異なるアプローチを比較するLiveStreamをチェックしてください。