既存のアプリとの統合
React Nativeは、新しいモバイルアプリをゼロから開発する際に非常に役立ちます。しかし、既存のネイティブアプリケーションに単一のビューやユーザフローを追加する場合にも有効です。いくつかのステップを踏むことで、新しいReact Nativeベースの機能、画面、ビューなどを追加できます。
具体的な手順は、対象とするプラットフォームによって異なります。
- Android (Java & Kotlin)
- iOS (Objective-CとSwift)
キーコンセプト
React NativeコンポーネントをAndroidアプリケーションに統合するためのキーは、次のとおりです。
- 正しいディレクトリ構造を設定する。
- 必要なNPM依存関係をインストールする。
- React NativeをGradle構成に追加する。
- 最初のReact Native画面のTypeScriptコードを記述する。
- ReactActivityを使用して、React NativeをAndroidコードと統合する。
- バンドラーを実行し、アプリが動作することを確認して統合をテストする。
コミュニティテンプレートの使用
このガイドに従う際には、React Native Community Templateを参考に使用することをお勧めします。テンプレートには、最小限のAndroidアプリが含まれており、React Nativeを既存のAndroidアプリに統合する方法を理解するのに役立ちます。
前提条件
開発環境の設定およびフレームワークなしのReact Nativeの使用に関するガイドに従って、Android用のReact Nativeアプリをビルドするための開発環境を構成します。また、このガイドでは、Activityの作成やAndroidManifest.xml
ファイルの編集など、Android開発の基本を理解していることを前提としています。
1. ディレクトリ構造の設定
スムーズなエクスペリエンスを実現するために、統合されたReact Nativeプロジェクト用の新しいフォルダを作成し、次に既存のAndroidプロジェクトを/android
サブフォルダに移動します。
2. NPM依存関係のインストール
ルートディレクトリに移動し、次のコマンドを実行します。
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.75-stable/template/package.json
これにより、コミュニティテンプレートからpackage.json
ファイルがプロジェクトにコピーされます。
次に、次のコマンドを実行してNPMパッケージをインストールします。
- npm
- Yarn
npm install
yarn install
インストールプロセスによって、新しいnode_modules
フォルダが作成されました。このフォルダには、プロジェクトをビルドするために必要なすべてのJavaScript依存関係が保存されます。
node_modules/
を.gitignore
ファイルに追加します(コミュニティのデフォルトはこちら)。
3. React Nativeをアプリに追加する
Gradleの設定
React Nativeは、React Native Gradle Pluginを使用して依存関係とプロジェクト設定を構成します。
まず、settings.gradle
ファイルを編集し、次の行を追加します(コミュニティテンプレートから推奨されているように)。
// Configures the React Native Gradle Settings plugin used for autolinking
pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
plugins { id("com.facebook.react.settings") }
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
// If using .gradle.kts files:
// extensions.configure<com.facebook.react.ReactSettingsExtension> { autolinkLibrariesFromCommand() }
includeBuild("../node_modules/@react-native/gradle-plugin")
// Include your existing Gradle modules here.
// include(":app")
次に、最上位のbuild.gradle
を開き、次の行を含める必要があります(コミュニティテンプレートから推奨されているように)。
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.3.1")
+ classpath("com.facebook.react:react-native-gradle-plugin")
}
}
これにより、React Native Gradle Plugin (RNGP) がプロジェクト内で利用可能になります。最後に、アプリケーションのbuild.gradle
ファイル(通常はapp
フォルダ内にある別のbuild.gradle
ファイルです - コミュニティテンプレートファイルを参考に使用できます)内に次の行を追加します。
apply plugin: "com.android.application"
+apply plugin: "com.facebook.react"
repositories {
mavenCentral()
}
dependencies {
// Other dependencies here
+ // Note: we intentionally don't specify the version number here as RNGP will take care of it.
+ // If you don't use the RNGP, you'll have to specify version manually.
+ implementation("com.facebook.react:react-android")
+ implementation("com.facebook.react:hermes-android")
}
+react {
+ // Needed to enable Autolinking - https://github.com/react-native-community/cli/blob/master/docs/autolinking.md
+ autolinkLibrariesWithApp()
+}
最後に、アプリケーションのgradle.properties
ファイルを開き、次の行を追加します(コミュニティテンプレートファイルを参考にしてください)。
+reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
+newArchEnabled=true
+hermesEnabled=true
マニフェストの設定
まず、AndroidManifest.xml
にインターネットパーミッションがあることを確認してください。
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication">
</application>
</manifest>
次に、デバッグAndroidManifest.xml
でクリアテキストトラフィックを有効にする必要があります。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
+ android:usesCleartextTraffic="true"
+ tools:targetApi="28"
/>
</manifest>
いつものように、コミュニティテンプレートからのAndroidManifest.xmlファイルを参照用に使用してください:mainとdebug
これは、アプリケーションがローカルバンドラーである[Metro][https://metrobundler.dev/]と通信するため必要です。HTTP経由で。
必ずデバッグマニフェストにのみ追加してください。
4. TypeScriptコードの記述
次に、React Nativeを統合するためにネイティブAndroidアプリケーションを実際に変更します。
最初に記述するコードは、アプリケーションに統合される新しい画面の実際のReact Nativeコードです。
index.js
ファイルの作成
まず、React Nativeプロジェクトのルートに空のindex.js
ファイルを作成します。
index.js
はReact Nativeアプリケーションの開始点であり、常に必要です。これは、React Nativeコンポーネントまたはアプリケーションの一部である他のファイルをimport
する小さなファイルであることもあれば、必要なすべてのコードを含むこともあります。
index.js
は次のようになります(コミュニティテンプレートファイルを参照してください)。
import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);
App.tsx
ファイルの作成
App.tsx
ファイルを作成しましょう。これは、TypeScriptファイルであり、JSX式を持つことができます。これには、Androidアプリケーションに統合するルートReact Nativeコンポーネントが含まれます(リンク)。
import React from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
useColorScheme,
View,
} from 'react-native';
import {
Colors,
DebugInstructions,
Header,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
function App(): React.JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
};
return (
<SafeAreaView style={backgroundStyle}>
<StatusBar
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
backgroundColor={backgroundStyle.backgroundColor}
/>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={backgroundStyle}>
<Header />
<View
style={{
backgroundColor: isDarkMode
? Colors.black
: Colors.white,
padding: 24,
}}>
<Text style={styles.title}>Step One</Text>
<Text>
Edit <Text style={styles.bold}>App.tsx</Text> to
change this screen and see your edits.
</Text>
<Text style={styles.title}>See your changes</Text>
<ReloadInstructions />
<Text style={styles.title}>Debug</Text>
<DebugInstructions />
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
title: {
fontSize: 24,
fontWeight: '600',
},
bold: {
fontWeight: '700',
},
});
export default App;
コミュニティテンプレートファイルを参考にしてください。
5. Androidコードとの統合
次に、React Nativeランタイムを開始し、Reactコンポーネントをレンダリングするように指示するために、ネイティブコードをいくつか追加する必要があります。
Applicationクラスの更新
まず、Application
クラスを次のように更新して、React Nativeを正しく初期化する必要があります。
- Java
- Kotlin
package <your-package-here>;
import android.app.Application;
+import com.facebook.react.PackageList;
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactHost;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
+import com.facebook.react.defaults.DefaultReactHost;
+import com.facebook.react.defaults.DefaultReactNativeHost;
+import com.facebook.soloader.SoLoader;
+import com.facebook.react.soloader.OpenSourceMergedSoMapping
+import java.util.List;
-class MainApplication extends Application {
+class MainApplication extends Application implements ReactApplication {
+ @Override
+ public ReactNativeHost getReactNativeHost() {
+ return new DefaultReactNativeHost(this) {
+ @Override
+ protected List<ReactPackage> getPackages() { return new PackageList(this).getPackages(); }
+ @Override
+ protected String getJSMainModuleName() { return "index"; }
+ @Override
+ public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; }
+ @Override
+ protected boolean isNewArchEnabled() { return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; }
+ @Override
+ protected Boolean isHermesEnabled() { return BuildConfig.IS_HERMES_ENABLED; }
+ };
+ }
+ @Override
+ public ReactHost getReactHost() {
+ return DefaultReactHost.getDefaultReactHost(getApplicationContext(), getReactNativeHost());
+ }
@Override
public void onCreate() {
super.onCreate();
+ SoLoader.init(this, OpenSourceMergedSoMapping);
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
+ DefaultNewArchitectureEntryPoint.load();
+ }
}
}
// package <your-package-here>
import android.app.Application
+import com.facebook.react.PackageList
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactHost
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
+import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
+import com.facebook.react.defaults.DefaultReactNativeHost
+import com.facebook.soloader.SoLoader
-class MainApplication : Application() {
+class MainApplication : Application(), ReactApplication {
+ override val reactNativeHost: ReactNativeHost =
+ object : DefaultReactNativeHost(this) {
+ override fun getPackages(): List<ReactPackage> = PackageList(this).packages
+ override fun getJSMainModuleName(): String = "index"
+ override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
+ override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
+ override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
+ }
+ override val reactHost: ReactHost
+ get() = getDefaultReactHost(applicationContext, reactNativeHost)
override fun onCreate() {
super.onCreate()
+ SoLoader.init(this, false)
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
+ load()
+ }
}
}
いつものように、MainApplication.ktコミュニティテンプレートファイルを参考にしてください。
ReactActivity
の作成
最後に、ReactActivity
を拡張し、React Nativeコードをホストする新しいActivity
を作成する必要があります。このアクティビティは、React Nativeランタイムを開始し、Reactコンポーネントをレンダリングする役割を担います。
- Java
- Kotlin
// package <your-package-here>;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;
public class MyReactActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "HelloWorld";
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new DefaultReactActivityDelegate(this, getMainComponentName(), DefaultNewArchitectureEntryPoint.getFabricEnabled());
}
}
// package <your-package-here>
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
class MyReactActivity : ReactActivity() {
override fun getMainComponentName(): String = "HelloWorld"
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}
いつものように、MainActivity.ktコミュニティテンプレートファイルを参考にしてください。
新しいActivityを作成するたびに、AndroidManifest.xml
ファイルに追加する必要があります。また、MyReactActivity
のテーマをTheme.AppCompat.Light.NoActionBar
(またはActionBar以外の任意のテーマ)に設定する必要があります。そうしないと、アプリケーションがReact Native画面の上にActionBarをレンダリングします。
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication">
+ <activity
+ android:name=".MyReactActivity"
+ android:label="@string/app_name"
+ android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+ </activity>
</application>
</manifest>
これで、アクティビティがJavaScriptコードを実行する準備ができました。
6. 統合のテスト
アプリケーションとのReact Nativeの統合に関するすべての基本ステップを完了しました。次に、Metroバンドラーを起動して、TypeScriptアプリケーションコードをバンドルにビルドします。MetroのHTTPサーバーは、開発環境のlocalhost
からシミュレーターまたはデバイスにバンドルを共有します。これにより、ホットリロードが可能になります。
まず、プロジェクトのルートに次のようにmetro.config.js
ファイルを作成する必要があります。
const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);
コミュニティテンプレートファイルのmetro.config.jsファイルを参考として確認できます。
構成ファイルを配置したら、バンドラーを実行できます。プロジェクトのルートディレクトリで次のコマンドを実行します。
- npm
- Yarn
npm start
yarn start
次に、Androidアプリを通常どおりにビルドして実行します。
アプリ内のReactを利用したアクティビティに到達すると、開発サーバーからJavaScriptコードがロードされ、表示されます。

Android Studioでリリースビルドを作成する
Android Studioを使用してリリースビルドを作成することもできます。以前から存在していたネイティブAndroidアプリのリリースビルドを作成するのと同じくらい簡単です。
React Native Gradle プラグインは、JS コードを APK/App Bundle 内にバンドルする処理を行います。
Android Studio を使用していない場合は、次のコマンドでリリースビルドを作成できます。
cd android
# For a Release APK
./gradlew :app:assembleRelease
# For a Release AAB
./gradlew :app:bundleRelease
次は?
この時点で、通常どおりアプリの開発を続けることができます。React Native の操作について詳しくは、デバッグとデプロイのドキュメントを参照してください。
キーコンセプト
React Native コンポーネントを iOS アプリケーションに統合するためのキーとなるのは、以下の点です。
- 正しいディレクトリ構造を設定する。
- 必要なNPM依存関係をインストールする。
- React Native を Podfile 構成に追加します。
- 最初のReact Native画面のTypeScriptコードを記述する。
RCTRootView
を使用して React Native を iOS コードと統合します。- バンドラーを実行し、アプリが動作することを確認して統合をテストする。
コミュニティテンプレートの使用
このガイドに従う際は、React Native Community Template を参考にすることをお勧めします。このテンプレートには、**最小限の iOS アプリ**が含まれており、React Native を既存の iOS アプリに統合する方法を理解するのに役立ちます。
前提条件
開発環境のセットアップと、フレームワークを使用しない React Native のガイドに従って、iOS 用の React Native アプリを構築するための開発環境を構成してください。また、このガイドでは、UIViewController
の作成や Podfile
ファイルの編集など、iOS 開発の基本を理解していることを前提としています。
1. ディレクトリ構造の設定
スムーズなエクスペリエンスを確保するために、統合された React Native プロジェクト用の新しいフォルダーを作成し、次に**既存の iOS プロジェクトを** /ios
サブフォルダーに**移動します**。
2. NPM依存関係のインストール
ルートディレクトリに移動し、次のコマンドを実行します。
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.76-stable/template/package.json
これにより、package.json
ファイルが Community テンプレートからプロジェクトにコピーされます。
次に、次のコマンドを実行してNPMパッケージをインストールします。
- npm
- Yarn
npm install
yarn install
インストールプロセスによって、新しいnode_modules
フォルダが作成されました。このフォルダには、プロジェクトをビルドするために必要なすべてのJavaScript依存関係が保存されます。
node_modules/
を .gitignore
ファイルに追加します (ここでは Community のデフォルトを使用します)。
3. 開発ツールのインストール
Xcode 用コマンドラインツール
コマンドラインツールをインストールします。Xcode メニューで **[設定...] (または [環境設定...])** を選択します。[場所] パネルに移動し、[コマンドラインツール] ドロップダウンで最新バージョンを選択してツールをインストールします。
CocoaPods
CocoaPods は、iOS および macOS 開発用のパッケージ管理ツールです。これを使用して、実際の React Native フレームワークコードを現在のプロジェクトにローカルで追加します。
Homebrew を使用して CocoaPods をインストールすることをお勧めします。
brew install cocoapods
4. アプリへの React Native の追加
CocoaPods の構成
CocoaPods を構成するには、2 つのファイルが必要です。
- 必要な Ruby の依存関係を定義する **Gemfile**。
- 依存関係を正しくインストールする方法を定義する **Podfile**。
**Gemfile** の場合は、プロジェクトのルートディレクトリに移動し、次のコマンドを実行します。
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.76-stable/template/Gemfile
これにより、テンプレートから Gemfile がダウンロードされます。同様に、**Podfile** の場合は、プロジェクトの ios
フォルダーに移動し、次を実行します。
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.76-stable/template/ios/Podfile
Gemfile と Podfile については、Community Template を参考にしてください。
次に、Ruby gem と Pod をインストールするために、いくつかの追加コマンドを実行する必要があります。ios
フォルダーに移動し、次のコマンドを実行します。
bundle install
bundle exec pod install
最初のコマンドは Ruby の依存関係をインストールし、2 番目のコマンドは React Native コードをアプリケーションに実際に統合して、iOS ファイルが React Native ヘッダーをインポートできるようにします。
5. TypeScript コードの記述
ここで、実際にネイティブ iOS アプリケーションを変更して React Native を統合します。
最初に記述するコードは、アプリケーションに統合される新しい画面の実際のReact Nativeコードです。
index.js
ファイルの作成
まず、React Nativeプロジェクトのルートに空のindex.js
ファイルを作成します。
index.js
はReact Nativeアプリケーションの開始点であり、常に必要です。これは、React Nativeコンポーネントまたはアプリケーションの一部である他のファイルをimport
する小さなファイルであることもあれば、必要なすべてのコードを含むこともあります。
index.js
は次のようになります (ここでは Community テンプレートファイルを参考にしてください)。
import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);
App.tsx
ファイルの作成
App.tsx
ファイルを作成しましょう。これは、TypeScript ファイルであり、JSX 式を含めることができます。これには、iOS アプリケーションに統合するルート React Native コンポーネントが含まれています (リンク)。
import React from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
useColorScheme,
View,
} from 'react-native';
import {
Colors,
DebugInstructions,
Header,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
function App(): React.JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
};
return (
<SafeAreaView style={backgroundStyle}>
<StatusBar
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
backgroundColor={backgroundStyle.backgroundColor}
/>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={backgroundStyle}>
<Header />
<View
style={{
backgroundColor: isDarkMode
? Colors.black
: Colors.white,
padding: 24,
}}>
<Text style={styles.title}>Step One</Text>
<Text>
Edit <Text style={styles.bold}>App.tsx</Text> to
change this screen and see your edits.
</Text>
<Text style={styles.title}>See your changes</Text>
<ReloadInstructions />
<Text style={styles.title}>Debug</Text>
<DebugInstructions />
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
title: {
fontSize: 24,
fontWeight: '600',
},
bold: {
fontWeight: '700',
},
});
export default App;
コミュニティテンプレートファイルを参考にしてください。
5. iOS コードとの統合
次に、React Nativeランタイムを開始し、Reactコンポーネントをレンダリングするように指示するために、ネイティブコードをいくつか追加する必要があります。
要件
React Native は AppDelegate
で動作することになっています。以下の部分は、AppDelegate
が次のようになっていることを前提としています。
- ObjectiveC
- Swift
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate {
UIWindow *window;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
window = [UIWindow new];
window.rootViewController = [ViewController new];
[window makeKeyAndVisible];
return YES;
}
@end
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow()
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
return true
}
}
AppDelegate
クラスの更新
まず、AppDelegate
を拡張して、React Native が提供するクラスの 1 つである RCTAppDelegate
から継承する必要があります。
- ObjectiveC
- Swift
これを実現するには、AppDelegate.h
ファイルと AppDelegate.m
ファイルを変更する必要があります。
AppDelegate.h
ファイルを開き、次のように変更します (公式テンプレートの AppDelegate.h を参考にしてください)。
#import <UIKit/UIKit.h>
+#import <React-RCTAppDelegate/RCTAppDelegate.h>
-@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@interface AppDelegate : RCTAppDelegate
@end
AppDelegate.mm
ファイルを開き、次のように変更します (公式テンプレートの AppDelegate.mm を参考にしてください)。
#import "AppDelegate.h"
#import "ViewController.h"
+#import <React/RCTBundleURLProvider.h>
@interface AppDelegate ()
@end
@implementation AppDelegate {
UIWindow *window;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ self.automaticallyLoadReactNativeWindow = NO;
+ return [super application:application didFinishLaunchingWithOptions:launchOptions];
window = [UIWindow new];
window.rootViewController = [ViewController new];
[window makeKeyAndVisible];
return YES;
}
+- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
+{
+ return [self bundleURL];
+}
+- (NSURL *)bundleURL
+{
+#if DEBUG
+ return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
+#else
+ return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
+#endif
+}
@end
上記のコードを見てみましょう。
RCTAppDelegate
から継承し、RCTAppDelegate
のapplication:didFinishLaunchingWithOptions
を呼び出しています。これにより、すべての React Native 初期化プロセスがベースクラスに委譲されます。automaticallyLoadReactNativeWindow
をNO
に設定することで、RCTAppDelegate
をカスタマイズしています。このステップでは、アプリがUIWindow
を処理しており、React Native はそれを心配する必要がないことを React Native に指示します。sourceURLForBridge:
メソッドとbundleURL
メソッドは、レンダリングする必要がある JS バンドルが React Native でどこにあるかをアプリに伝えるために使用されます。sourceURLForBridge:
は古いアーキテクチャのものであり、新しいアーキテクチャで必要なbundleURL
メソッドに決定を委ねていることがわかります。
これを実現するには、AppDelegate.swift
を変更する必要があります。
AppDelegate.swift
ファイルを開き、次のように変更します (公式テンプレートの AppDelegate.swift を参考にしてください)。
import UIKit
+import React_RCTAppDelegate
+import React_RCTAppDelegate
@main
-class AppDelegate: UIResponder, UIApplicationDelegate {
+class AppDelegate: RCTAppDelegate {
- var window: UIWindow?
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
+ self.automaticallyLoadReactNativeWindow = false
+ super.application(application, didFinishLaunchingWithOptions: launchOptions)
window = UIWindow()
- window?.rootViewController = ViewController()
- window?.makeKeyAndVisible()
+ window.rootViewController = ViewController()
+ window.makeKeyAndVisible()
return true
}
+ override func sourceURL(for bridge: RCTBridge) -> URL? {
+ self.bundleURL()
+ }
+ override func bundleURL() -> URL? {
+#if DEBUG
+ RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
+#else
+ Bundle.main.url(forResource: "main", withExtension: "jsbundle")
+#endif
+ }
}
上記のコードを見てみましょう。
RCTAppDelegate
から継承し、RCTAppDelegate
のapplication(_:didFinishLaunchingWithOptions:)
を呼び出しています。これにより、すべての React Native 初期化プロセスがベースクラスに委譲されます。automaticallyLoadReactNativeWindow
をfalse
に設定することで、RCTAppDelegate
をカスタマイズしています。このステップでは、アプリがUIWindow
を処理しており、React Native はそれを心配する必要がないことを React Native に指示します。sourceURLForBridge(for:)
メソッドとbundleURL()
メソッドは、レンダリングする必要がある JS バンドルが React Native でどこにあるかをアプリに伝えるために使用されます。sourceURLForBridge(for:)
は古いアーキテクチャのものであり、新しいアーキテクチャで必要なbundleURL()
メソッドに決定を委ねていることがわかります。
rootViewController で React Native ビューを提示する
最後に、React Native ビューを提示できます。そのためには、JS コンテンツをロードできるビューをホストできる新しい View Controller が必要です。
- Xcode から、新しい
UIViewController
を作成しましょう (ReactViewController
と呼びましょう)。 - 最初の
ViewController
にReactViewController
をモーダルで表示させます。アプリに応じて、いくつかの方法があります。この例では、React Native をモーダルで表示するボタンがあることを前提としています。
- ObjectiveC
- Swift
#import "ViewController.h"
+#import "ReactViewController.h"
@interface ViewController ()
@end
- @implementation ViewController
+@implementation ViewController {
+ ReactViewController *reactViewController;
+}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = UIColor.systemBackgroundColor;
+ UIButton *button = [UIButton new];
+ [button setTitle:@"Open React Native" forState:UIControlStateNormal];
+ [button setTitleColor:UIColor.systemBlueColor forState:UIControlStateNormal];
+ [button setTitleColor:UIColor.blueColor forState:UIControlStateHighlighted];
+ [button addTarget:self action:@selector(presentReactNative) forControlEvents:UIControlEventTouchUpInside];
+ [self.view addSubview:button];
+ button.translatesAutoresizingMaskIntoConstraints = NO;
+ [NSLayoutConstraint activateConstraints:@[
+ [button.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
+ [button.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
+ [button.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor],
+ [button.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
+ ]];
}
+- (void)presentReactNative
+{
+ if (reactViewController == NULL) {
+ reactViewController = [ReactViewController new];
+ }
+ [self presentViewController:reactViewController animated:YES completion:nil];
+}
@end
import UIKit
class ViewController: UIViewController {
+ var reactViewController: ReactViewController?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor = .systemBackground
+ let button = UIButton()
+ button.setTitle("Open React Native", for: .normal)
+ button.setTitleColor(.systemBlue, for: .normal)
+ button.setTitleColor(.blue, for: .highlighted)
+ button.addAction(UIAction { [weak self] _ in
+ if reactViewController == nil {
+ reactViewController = ReactViewController()
+ }
+ self?.present(reactViewController, animated: true)
+ }, for: .touchUpInside)
+ self.view.addSubview(button)
+
+ button.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ button.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
+ button.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
+ button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
+ button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
+ ])
}
}
ReactViewController
コードを次のように更新します。
- ObjectiveC
- Swift
#import "ReactViewController.h"
+#import <React-RCTAppDelegate/RCTRootViewFactory.h>
+#import <React-RCTAppDelegate/RCTAppDelegate.h>
@interface ReactViewController ()
@end
@implementation ReactViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
+ RCTRootViewFactory *factory = ((RCTAppDelegate *)RCTSharedApplication().delegate).rootViewFactory;
+ self.view = [factory viewWithModuleName:@"HelloWorld"];
}
@end
import UIKit
+import React_RCTAppDelegate
class ReactViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
+ let factory = (RCTSharedApplication()?.delegate as? RCTAppDelegate)?.rootViewFactory
+ self.view = factory?.view(withModuleName: "HelloWorld")
}
}
- サンドボックススクリプトを無効にしてください。これを実現するには、Xcode でアプリをクリックし、次にビルド設定をクリックします。スクリプトをフィルター処理し、
User Script Sandboxing
をNO
に設定します。このステップは、React Native に付属している Hermes エンジンのデバッグバージョンとリリースバージョンを適切に切り替えるために必要です。
;
6. 統合のテスト
アプリケーションとのReact Nativeの統合に関するすべての基本ステップを完了しました。次に、Metroバンドラーを起動して、TypeScriptアプリケーションコードをバンドルにビルドします。MetroのHTTPサーバーは、開発環境のlocalhost
からシミュレーターまたはデバイスにバンドルを共有します。これにより、ホットリロードが可能になります。
まず、プロジェクトのルートに次のようにmetro.config.js
ファイルを作成する必要があります。
const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);
コミュニティテンプレートファイルのmetro.config.jsファイルを参考として確認できます。
構成ファイルを配置したら、バンドラーを実行できます。プロジェクトのルートディレクトリで次のコマンドを実行します。
- npm
- Yarn
npm start
yarn start
これで、通常どおり iOS アプリをビルドして実行できます。
アプリ内のReactを利用したアクティビティに到達すると、開発サーバーからJavaScriptコードがロードされ、表示されます。

Xcode でのリリースビルドの作成
Xcode を使用してリリースビルドを作成することもできます。追加のステップは、アプリがビルドされたときに実行されるスクリプトを追加して、JS と画像を iOS アプリケーションにパッケージ化することだけです。
- Xcode でアプリケーションを選択します。
Build Phases
をクリックします。- 左上の
+
をクリックし、New Run Script Phase
を選択します。 Run Script
行をクリックし、スクリプトの名前をBundle React Native code and images
に変更します。- 以下のスクリプトをテキストボックスに貼り付けてください
set -e
WITH_ENVIRONMENT="$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh"
REACT_NATIVE_XCODE="$REACT_NATIVE_PATH/scripts/react-native-xcode.sh"
/bin/sh -c "$WITH_ENVIRONMENT $REACT_NATIVE_XCODE"
[CP] Embed Pods Frameworks
という名前のスクリプトの前に、このスクリプトをドラッグアンドドロップしてください。
これで、リリース用にアプリをビルドすると、期待どおりに動作するようになります。
次は?
この時点で、通常どおりアプリの開発を続けることができます。React Native の操作について詳しくは、デバッグとデプロイのドキュメントを参照してください。