与现有应用集成
当你从头开始开发新的移动应用时,React Native 非常有用。但是,它也适用于向现有原生应用添加单个视图或用户流。只需几个步骤,你就可以添加新的基于 React Native 的功能、屏幕、视图等。
¥React Native is great when you are starting a new mobile app from scratch. However, it also works well for adding a single view or user flow to existing native applications. With a few steps, you can add new React Native based features, screens, views, etc.
具体步骤会有所不同,具体取决于你的目标平台。
¥The specific steps are different depending on what platform you're targeting.
- Android (Java & Kotlin)
- iOS (Objective-C and Swift)
关键概念
¥Key Concepts
将 React Native 组件集成到 Android 应用中的关键是:
¥The keys to integrating React Native components into your Android application are to:
-
设置正确的目录结构。
¥Set up the correct directory structure.
-
安装必要的 NPM 依赖。
¥Install the necessary NPM dependencies.
-
将 React Native 添加到你的 Gradle 配置中。
¥Adding React Native to your Gradle configuration.
-
为你的第一个 React Native 屏幕编写 TypeScript 代码。
¥Writing the TypeScript code for your first React Native screen.
-
使用 ReactActivity 将 React Native 与你的 Android 代码集成。
¥Integrate React Native with your Android code using a ReactActivity.
-
通过运行打包程序并查看你的应用的运行情况来测试你的集成。
¥Testing your integration by running the bundler and seeing your app in action.
使用社区模板
¥Using the Community Template
在你遵循本指南时,我们建议你使用 React Native 社区模板 作为参考。模板包含一个最小的 Android 应用,将帮助你了解如何将 React Native 集成到现有的 Android 应用中。
¥While you follow this guide, we suggest you to use the React Native Community Template as reference. The template contains a minimal Android app and will help you understanding how to integrate React Native into an existing Android app.
先决条件
¥Prerequisites
按照 设置你的开发环境 上的指南并使用 无需框架的 React Native 配置你的开发环境以构建适用于 Android 的 React Native 应用。本指南还假设你熟悉 Android 开发的基础知识,例如创建活动和编辑 AndroidManifest.xml
文件。
¥Follow the guide on setting up your development environment and using React Native without a framework to configure your development environment for building React Native apps for Android.
This guide also assumes you're familiar with the basics of Android development such as creating Activities and editing the AndroidManifest.xml
file.
1. 设置目录结构
¥ Set up directory structure
为了确保流畅的体验,请为集成的 React Native 项目创建一个新文件夹,然后将现有的 Android 项目移动到 /android
子文件夹。
¥To ensure a smooth experience, create a new folder for your integrated React Native project, then move your existing Android project to the /android
subfolder.
2. 安装 NPM 依赖
¥ Install NPM dependencies
转到根目录并运行以下命令:
¥Go to the root directory and run the following command:
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.75-stable/template/package.json
这会将 package.json
来自社区模板的文件 复制到你的项目中。
¥This will copy the package.json
file from the Community template to your project.
接下来,通过运行安装 NPM 包:
¥Next, install the NPM packages by running:
- npm
- Yarn
npm install
yarn install
安装过程创建了一个新的 node_modules
文件夹。此文件夹存储构建项目所需的所有 JavaScript 依赖。
¥Installation process has created a new node_modules
folder. This folder stores all the JavaScript dependencies required to build your project.
将 node_modules/
添加到你的 .gitignore
文件(此处为 社区默认)。
¥Add node_modules/
to your .gitignore
file (here the Community default one).
3. 将 React Native 添加到你的应用
¥ Adding React Native to your app
配置 Gradle
¥Configuring Gradle
React Native 使用 React Native Gradle 插件来配置依赖和项目设置。
¥React Native uses the React Native Gradle Plugin to configure your dependencies and project setup.
首先,让我们编辑你的 settings.gradle
文件,添加这些行(如 社区模板 所建议的):
¥First, let's edit your settings.gradle
file by adding those lines (as suggested from the Community template):
// 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
并包含此行(如 社区模板 所建议的):
¥Then you need to open your top level build.gradle
and include this line (as suggested from the Community template):
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 插件 (RNGP) 在你的项目中可用。最后,在应用的 build.gradle
文件中添加这些行(它通常是 app
文件夹中的另一个 build.gradle
文件 - 你可以使用 社区模板文件作为参考):
¥This makes sure the React Native Gradle Plugin (RNGP) is available inside your project.
Finally, add those lines inside your Applications's build.gradle
file (it's a different build.gradle
file usually inside your app
folder - you can use the Community template file as reference):
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
文件并添加以下行(此处为 社区模板文件作为参考):
¥Finally, open your application gradle.properties
files and add the following line (here the Community template file as reference):
+reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
+newArchEnabled=true
+hermesEnabled=true
配置你的清单
¥Configuring your manifest
首先,确保你的 AndroidManifest.xml
具有 Internet 权限:
¥First, make sure you have the Internet permission in your 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
中启用 明文流量:
¥Then you need to enable cleartext traffic in your debug 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
¥As usual, here the AndroidManifest.xml file from the Community template to use as a reference: main and debug
这是必需的,因为你的应用将通过 HTTP 与你的本地打包器 Metro 进行通信。
¥This is needed as your application will communicate with your local bundler, [Metro][https://metrobundler.dev/], via HTTP.
确保仅将其添加到你的调试清单中。
¥Make sure you add this only to your debug manifest.
4. 编写 TypeScript 代码
¥ Writing the TypeScript Code
现在我们将实际修改原生 Android 应用以集成 React Native。
¥Now we will actually modify the native Android application to integrate React Native.
我们将编写的第一段代码是新屏幕的实际 React Native 代码,它将集成到我们的应用中。
¥The first bit of code we will write is the actual React Native code for the new screen that will be integrated into our application.
创建 index.js
文件
¥Create a index.js
file
首先,在 React Native 项目的根目录中创建一个空的 index.js
文件。
¥First, create an empty index.js
file in the root of your React Native project.
index.js
是 React Native 应用的起点,并且始终是必需的。它可以是一个小文件,或者是 React Native 组件或应用中的其他文件,也可以包含它所需的所有代码。
¥index.js
is the starting point for React Native applications, and it is always required. It can be a small file that import
s other file that are part of your React Native component or application, or it can contain all the code that is needed for it.
我们的 index.js 应该如下所示(这里是 社区模板文件作为参考):
¥Our index.js should look as follows (here the Community template file as reference):
import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);
创建 App.tsx
文件
¥Create a App.tsx
file
让我们创建一个 App.tsx
文件。这是一个可以有 JSX 表达式的 TypeScript 文件。它包含我们将集成到 Android 应用 (link) 中的根 React Native 组件:
¥Let's create an App.tsx
file. This is a TypeScript file that can have JSX expressions. It contains the root React Native component that we will integrate into our Android application (link):
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;
这里是 社区模板文件作为参考
¥Here the Community template file as reference
5. 与你的 Android 代码集成
¥ Integrating with your Android code
我们现在需要添加一些原生代码以启动 React Native 运行时并告诉它渲染我们的 React 组件。
¥We now need to add some native code in order to start the React Native runtime and tell it to render our React components.
更新你的应用类
¥Updating your Application class
首先,我们需要更新你的 Application
类以正确初始化 React Native,如下所示:
¥First, we need to update your Application
class to properly initialize React Native as follows:
- 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 社区模板文件作为参考
¥As usual, here the MainApplication.kt Community template file as reference
创建 ReactActivity
¥Creating a ReactActivity
最后,我们需要创建一个新的 Activity
,它将扩展 ReactActivity
并托管 React Native 代码。此活动将负责启动 React Native 运行时并渲染 React 组件。
¥Finally, we need to create a new Activity
that will extend ReactActivity
and host the React Native code. This activity will be responsible for starting the React Native runtime and rendering the React component.
- 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 社区模板文件作为参考
¥As usual, here the MainActivity.kt Community template file as reference
每当你创建新活动时,都需要将其添加到你的 AndroidManifest.xml
文件中。你还需要将 MyReactActivity
的主题设置为 Theme.AppCompat.Light.NoActionBar
(或任何非 ActionBar 主题),否则你的应用将在 React Native 屏幕顶部渲染 ActionBar:
¥Whenever you create a new Activity, you need to add it to your AndroidManifest.xml
file. You also need set the theme of MyReactActivity
to Theme.AppCompat.Light.NoActionBar
(or to any non-ActionBar theme) as otherwise your application will render an ActionBar on top of your React Native screen:
<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>
现在你的 Activity 已准备好运行一些 JavaScript 代码。
¥Now your activity is ready to run some JavaScript code.
6. 测试你的集成
¥ Test your integration
你已完成将 React Native 与你的应用集成的所有基本步骤。现在我们将启动 Metro 打包器 将你的 TypeScript 应用代码构建成一个包。Metro 的 HTTP 服务器将你开发环境中的 localhost
中的打包包共享到模拟器或设备。这允许 热重载。
¥You have completed all the basic steps to integrate React Native with your application. Now we will start the Metro bundler to build your TypeScript application code into a bundle. Metro's HTTP server shares the bundle from localhost
on your developer environment to a simulator or device. This allows for hot reloading.
首先,你需要在项目的根目录中创建一个 metro.config.js
文件,如下所示:
¥First, you need to create a metro.config.js
file in the root of your project as follows:
const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);
你可以从社区模板文件中检出 metro.config.js 文件 作为参考。
¥You can checkout the metro.config.js file from the Community template file as reference.
一旦配置文件到位,你就可以运行打包器。在项目的根目录中运行以下命令:
¥Once you have the config file in place, you can run the bundler. Run the following command in the root directory of your project:
- npm
- Yarn
npm start
yarn start
现在正常构建并运行你的 Android 应用。
¥Now build and run your Android app as normal.
一旦你到达应用内部的 React 驱动活动,它应该从开发服务器加载 JavaScript 代码并显示:
¥Once you reach your React-powered Activity inside the app, it should load the JavaScript code from the development server and display:
在 Android Studio 中创建发布版本
¥Creating a release build in Android Studio
你也可以使用 Android Studio 创建你的发布版本!它就像为你之前存在的原生 Android 应用创建发布版本一样快。
¥You can use Android Studio to create your release builds too! It’s as quick as creating release builds of your previously-existing native Android app.
React Native Gradle 插件将负责将 JS 代码打包在你的 APK/App Bundle 中。
¥The React Native Gradle Plugin will take care of bundling the JS code inside your APK/App Bundle.
如果你不使用 Android Studio,你可以使用以下方式创建发布版本:
¥If you're not using Android Studio, you can create a release build with:
cd android
# For a Release APK
./gradlew :app:assembleRelease
# For a Release AAB
./gradlew :app:bundleRelease
怎么办?
¥Now what?
此时,你可以像往常一样继续开发你的应用。请参阅我们的 debugging 和 deployment 文档,了解有关使用 React Native 的更多信息。
¥At this point you can continue developing your app as usual. Refer to our debugging and deployment docs to learn more about working with React Native.
关键概念
¥Key Concepts
将 React Native 组件集成到 iOS 应用中的关键是:
¥The keys to integrating React Native components into your iOS application are to:
-
设置正确的目录结构。
¥Set up the correct directory structure.
-
安装必要的 NPM 依赖。
¥Install the necessary NPM dependencies.
-
将 React Native 添加到你的 Podfile 配置中。
¥Adding React Native to your Podfile configuration.
-
为你的第一个 React Native 屏幕编写 TypeScript 代码。
¥Writing the TypeScript code for your first React Native screen.
-
使用
RCTRootView
将 React Native 与你的 iOS 代码集成。¥Integrate React Native with your iOS code using a
RCTRootView
. -
通过运行打包程序并查看你的应用的运行情况来测试你的集成。
¥Testing your integration by running the bundler and seeing your app in action.
使用社区模板
¥Using the Community Template
在你遵循本指南时,我们建议你使用 React Native 社区模板 作为参考。模板包含一个最小的 iOS 应用,将帮助你了解如何将 React Native 集成到现有的 iOS 应用中。
¥While you follow this guide, we suggest you to use the React Native Community Template as reference. The template contains a minimal iOS app and will help you understanding how to integrate React Native into an existing iOS app.
先决条件
¥Prerequisites
按照 设置你的开发环境 上的指南并使用 无需框架的 React Native 配置你的开发环境以构建适用于 iOS 的 React Native 应用。本指南还假设你熟悉 iOS 开发的基础知识,例如创建 UIViewController
和编辑 Podfile
文件。
¥Follow the guide on setting up your development environment and using React Native without a framework to configure your development environment for building React Native apps for iOS.
This guide also assumes you're familiar with the basics of iOS development such as creating a UIViewController
and editing the Podfile
file.
1. 设置目录结构
¥ Set up directory structure
为了确保流畅的体验,请为集成的 React Native 项目创建一个新文件夹,然后将现有的 iOS 项目移动到 /ios
子文件夹。
¥To ensure a smooth experience, create a new folder for your integrated React Native project, then move your existing iOS project to the /ios
subfolder.
2. 安装 NPM 依赖
¥ Install NPM dependencies
转到根目录并运行以下命令:
¥Go to the root directory and run the following command:
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.76-stable/template/package.json
这会将 package.json
来自社区模板的文件 复制到你的项目中。
¥This will copy the package.json
file from the Community template to your project.
接下来,通过运行安装 NPM 包:
¥Next, install the NPM packages by running:
- npm
- Yarn
npm install
yarn install
安装过程创建了一个新的 node_modules
文件夹。此文件夹存储构建项目所需的所有 JavaScript 依赖。
¥Installation process has created a new node_modules
folder. This folder stores all the JavaScript dependencies required to build your project.
将 node_modules/
添加到你的 .gitignore
文件(此处为 社区默认)。
¥Add node_modules/
to your .gitignore
file (here the Community default one).
3. 安装开发工具
¥ Install Development tools
Xcode 命令行工具
¥Command Line Tools for Xcode
安装命令行工具。选择设置...(或首选项...)在 Xcode 菜单中。转到“位置”面板并通过在“命令行工具”下拉列表中选择最新版本来安装工具。
¥Install the Command Line Tools. Choose Settings... (or Preferences...) in the Xcode menu. Go to the Locations panel and install the tools by selecting the most recent version in the Command Line Tools dropdown.
CocoaPods
CocoaPods 是一款用于 iOS 和 macOS 开发的包管理工具。我们使用它来将实际的 React Native 框架代码本地添加到你当前的项目中。
¥CocoaPods is a package management tool for iOS and macOS development. We use it to add the actual React Native framework code locally into your current project.
我们建议使用 Homebrew 安装 CocoaPods:
¥We recommend installing CocoaPods using Homebrew:
brew install cocoapods
4. 将 React Native 添加到你的应用
¥ Adding React Native to your app
配置 CocoaPods
¥Configuring CocoaPods
要配置 CocoaPods,我们需要两个文件:
¥To configure CocoaPods, we need two files:
-
定义我们需要哪些 Ruby 依赖的 Gemfile。
¥A Gemfile that defines which Ruby dependencies we need.
-
定义如何正确安装依赖的 Podfile。
¥A Podfile that defines how to properly install our dependencies.
对于 Gemfile,请转到项目的根目录并运行此命令
¥For the Gemfile, go to the root directory of your project and run this command
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.76-stable/template/Gemfile
这将从模板下载 Gemfile。同样,对于 Podfile,转到项目的 ios
文件夹并运行
¥This will download the Gemfile from the template.
Similarly, for the Podfile, go to the ios
folder of your project and run
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.76-stable/template/ios/Podfile
请使用社区模板作为 Gemfile 和 Podfile 的参考点。
¥Please use the Community Template as a reference point for the Gemfile and for the Podfile.
现在,我们需要运行几个额外的命令来安装 Ruby gem 和 Pods。导航到 ios
文件夹并运行以下命令:
¥Now, we need to run a couple of extra commands to install the Ruby gems and the Pods.
Navigate to the ios
folder and run the following commands:
bundle install
bundle exec pod install
第一个命令将安装 Ruby 依赖,第二个命令将实际将 React Native 代码集成到你的应用中,以便你的 iOS 文件可以导入 React Native 标头。
¥The first command will install the Ruby dependencies and the second command will actually integrate the React Native code in your application so that your iOS files can import the React Native headers.
5. 编写 TypeScript 代码
¥ Writing the TypeScript Code
现在我们将实际修改原生 iOS 应用以集成 React Native。
¥Now we will actually modify the native iOS application to integrate React Native.
我们将编写的第一段代码是新屏幕的实际 React Native 代码,它将集成到我们的应用中。
¥The first bit of code we will write is the actual React Native code for the new screen that will be integrated into our application.
创建 index.js
文件
¥Create a index.js
file
首先,在 React Native 项目的根目录中创建一个空的 index.js
文件。
¥First, create an empty index.js
file in the root of your React Native project.
index.js
是 React Native 应用的起点,并且始终是必需的。它可以是一个小文件,或者是 React Native 组件或应用中的其他文件,也可以包含它所需的所有代码。
¥index.js
is the starting point for React Native applications, and it is always required. It can be a small file that import
s other file that are part of your React Native component or application, or it can contain all the code that is needed for it.
我们的 index.js
应该如下所示(这里是 社区模板文件作为参考):
¥Our index.js
should look as follows (here the Community template file as reference):
import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);
创建 App.tsx
文件
¥Create a App.tsx
file
让我们创建一个 App.tsx
文件。这是一个可以有 JSX 表达式的 TypeScript 文件。它包含我们将集成到 iOS 应用 (link) 中的根 React Native 组件:
¥Let's create an App.tsx
file. This is a TypeScript file that can have JSX expressions. It contains the root React Native component that we will integrate into our iOS application (link):
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;
这里是 社区模板文件作为参考
¥Here the Community template file as reference
5. 与你的 iOS 代码集成
¥ Integrating with your iOS code
我们现在需要添加一些原生代码以启动 React Native 运行时并告诉它渲染我们的 React 组件。
¥We now need to add some native code in order to start the React Native runtime and tell it to render our React components.
要求
¥Requirements
React Native 应该与 AppDelegate
一起使用。以下部分假设你的 AppDelegate
如下所示:
¥React Native is supposed to work with the AppDelegate
. The following part assumes that your AppDelegate
looks like this:
- 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
类
¥Update the AppDelegate
class
首先,我们需要扩展 AppDelegate
以从 React Native 提供的一个类继承:RCTAppDelegate
。
¥First, we need to extends the AppDelegate
to inherit from one of the classes provided by React Native: RCTAppDelegate
.
- ObjectiveC
- Swift
为了实现这一点,我们必须修改 AppDelegate.h
文件和 AppDelegate.m
文件:
¥To achieve this, we have to modify the AppDelegate.h
file and the AppDelegate.m
files:
-
打开
AppDelegate.h
文件并按如下方式修改(请参阅官方模板的 AppDelegate.h 作为参考):¥Open the
AppDelegate.h
files and modify it as it follows (See the official template's AppDelegate.h as reference):
#import <UIKit/UIKit.h>
+#import <React-RCTAppDelegate/RCTAppDelegate.h>
-@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@interface AppDelegate : RCTAppDelegate
@end
-
打开
AppDelegate.mm
文件并按如下方式修改(请参阅官方模板的 AppDelegate.mm 作为参考)¥Open the
AppDelegate.mm
file and modify it as it follows (See the official template's AppDelegate.mm as reference
#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
让我们看看上面的代码:
¥Let's have a look at the code above:
-
我们继承自
RCTAppDelegate
,并将application:didFinishLaunchingWithOptions
称为RCTAppDelegate
。这会将所有 React Native 初始化过程委托给基类。¥We are inheriting from the
RCTAppDelegate
and we are calling theapplication:didFinishLaunchingWithOptions
of theRCTAppDelegate
. This delegates all the React Native initialization processes to the base class. -
我们通过将
automaticallyLoadReactNativeWindow
设置为NO
来自定义RCTAppDelegate
。此步骤指示 React Native 应用正在处理UIWindow
,React Native 不必担心这一点。¥We are customizing the
RCTAppDelegate
by setting theautomaticallyLoadReactNativeWindow
toNO
. This step instruct React Native that the app is handling theUIWindow
and React Native should not worry about that. -
应用使用方法
sourceURLForBridge:
和bundleURL
告诉 React Native 它可以在哪里找到需要渲染的 JS 包。sourceURLForBridge:
来自旧架构,你可以看到它将决定推迟到新架构所需的bundleURL
方法。¥The methods
sourceURLForBridge:
andbundleURL
are used by the App to tell to React Native where it can find the JS bundle that needs to be rendered. ThesourceURLForBridge:
is from the Old Architecture and you can see that it is deferring the decision to thebundleURL
method, required by the New Architecture.
为了实现这一点,我们必须修改 AppDelegate.swift
¥To achieve this, we have to modify the AppDelegate.swift
-
打开
AppDelegate.swift
文件并按如下方式修改(请参阅官方模板的 AppDelegate.swift 作为参考):¥Open the
AppDelegate.swift
files and modify it as it follows (See the official template's AppDelegate.swift as reference):
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
+ }
}
让我们看看上面的代码:
¥Let's have a look at the code above:
-
我们继承自
RCTAppDelegate
,并将application(_:didFinishLaunchingWithOptions:)
称为RCTAppDelegate
。这会将所有 React Native 初始化过程委托给基类。¥We are inheriting from the
RCTAppDelegate
and we are calling theapplication(_:didFinishLaunchingWithOptions:)
of theRCTAppDelegate
. This delegates all the React Native initialization processes to the base class. -
我们通过将
automaticallyLoadReactNativeWindow
设置为false
来自定义RCTAppDelegate
。此步骤指示 React Native 应用正在处理UIWindow
,React Native 不必担心这一点。¥We are customizing the
RCTAppDelegate
by setting theautomaticallyLoadReactNativeWindow
tofalse
. This step instruct React Native that the app is handling theUIWindow
and React Native should not worry about that. -
应用使用方法
sourceURLForBridge(for:)
和bundleURL()
告诉 React Native 它可以在哪里找到需要渲染的 JS 包。sourceURLForBridge(for:)
来自旧架构,你可以看到它将决定推迟到新架构所需的bundleURL()
方法。¥The methods
sourceURLForBridge(for:)
andbundleURL()
are used by the App to tell to React Native where it can find the JS bundle that needs to be rendered. ThesourceURLForBridge(for:)
is from the Old Architecture and you can see that it is deferring the decision to thebundleURL()
method, required by the New Architecture.
在 rootViewController 中渲染 React Native 视图
¥Presenting a React Native view in a rootViewController
最后,我们可以展示我们的 React Native 视图。为此,我们需要一个新的 View Controller 来托管一个视图,我们可以在其中加载 JS 内容。
¥Finally, we can present our React Native view. To do so, we need a new View Controller that can host a view in which we can load the JS content.
-
从 Xcode,让我们创建一个新的
UIViewController
(我们称之为ReactViewController
)。¥From Xcode, let's create a new
UIViewController
(Let's call itReactViewController
). -
让初始
ViewController
渲染ReactViewController
。有几种方法可以做到这一点,具体取决于你的应用。对于本示例,我们假设你有一个按钮,用于以 Modally 形式渲染 React Native。¥Have the Initial
ViewController
present theReactViewController
. There are several ways to do so, depending on your app. For this example, we assume that you have a button that presents React Native Modally.
- 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
代码:¥Update the
ReactViewController
code as it follows:
- 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")
}
}
-
确保禁用 Sandbox 脚本。要实现此目的,请在 Xcode 中单击你的应用,然后单击构建设置。过滤脚本并将
User Script Sandboxing
设置为NO
。此步骤是正确切换我们随 React Native 一起提供的 Hermes 引擎 的调试版和发布版所必需的。¥Make sure to disable the Sandbox scripting. To achieve this, in Xcode, click on your app, then on build settings. Filter for script and set the
User Script Sandboxing
toNO
. This step is needed to properly switch between the Debug and Release version of the Hermes engine that we ship with React Native.
;
6. 测试你的集成
¥ Test your integration
你已完成将 React Native 与你的应用集成的所有基本步骤。现在我们将启动 Metro 打包器 将你的 TypeScript 应用代码构建成一个包。Metro 的 HTTP 服务器将你开发环境中的 localhost
中的打包包共享到模拟器或设备。这允许 热重载。
¥You have completed all the basic steps to integrate React Native with your application. Now we will start the Metro bundler to build your TypeScript application code into a bundle. Metro's HTTP server shares the bundle from localhost
on your developer environment to a simulator or device. This allows for hot reloading.
首先,你需要在项目的根目录中创建一个 metro.config.js
文件,如下所示:
¥First, you need to create a metro.config.js
file in the root of your project as follows:
const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);
你可以从社区模板文件中检出 metro.config.js 文件 作为参考。
¥You can checkout the metro.config.js file from the Community template file as reference.
一旦配置文件到位,你就可以运行打包器。在项目的根目录中运行以下命令:
¥Once you have the config file in place, you can run the bundler. Run the following command in the root directory of your project:
- npm
- Yarn
npm start
yarn start
现在正常构建和运行你的 iOS 应用。
¥Now build and run your iOS app as normal.
一旦你到达应用内部的 React 驱动活动,它应该从开发服务器加载 JavaScript 代码并显示:
¥Once you reach your React-powered Activity inside the app, it should load the JavaScript code from the development server and display:
在 Xcode 中创建发布版本
¥Creating a release build in Xcode
你也可以使用 Xcode 创建你的发布版本!唯一的额外步骤是添加一个在构建应用时执行的脚本,以将你的 JS 和图片打包到 iOS 应用中。
¥You can use Xcode to create your release builds too! The only additional step is to add a script that is executed when the app is built to package your JS and images into the iOS application.
-
在 Xcode 中,选择你的应用
¥In Xcode, select your application
-
单击
Build Phases
¥Click on
Build Phases
-
单击左上角的
+
并选择New Run Script Phase
¥Click on the
+
in the top left corner and selectNew Run Script Phase
-
单击
Run Script
行并将脚本重命名为Bundle React Native code and images
¥Click on the
Run Script
line and rename the Script toBundle React Native code and images
-
在文本框中粘贴以下脚本
¥Paste in the text box the following script
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
的脚本之前。¥Drag and drop the script before the one called
[CP] Embed Pods Frameworks
.
现在,如果你为 Release 构建应用,它将按预期工作。
¥Now, if you build your app for Release, it will work as expected.
怎么办?
¥Now what?
此时,你可以像往常一样继续开发你的应用。请参阅我们的 debugging 和 deployment 文档,了解有关使用 React Native 的更多信息。
¥At this point you can continue developing your app as usual. Refer to our debugging and deployment docs to learn more about working with React Native.