Skip to main content

Welcome to Bridging Tutorial

You'll learn here, how to bring (almost) any native functionality to the React Native app. This set of guides will showcase possible types of native modules and views, how to structure packages with native code, how to use Android & iOS dependencies to bring the same native experience from non-cross-platform Android & iOS apps and many many more.

tip

If you are Expo enjoyer and you want to write native code in Expo project, Expo Modules is the way to go. However, you can still check following guides to learn some RN + native insights which will give you better overview and you'll appreciate Expo & Expo Modules even more!

Prerequisites

Most of the code you'll see here is written in one of native languages used for iOS or Android development. If you don't know the basics (primitive types, classes, interfaces, methods, etc.), it's not mandatory, but still recommended to (at least) read some introduction to the following langs:

You should also familiarize yourself with XCode and Android Studio as the main IDEs for mobile native development.

Getting Started

To start the tutorial, you need a sample app created with React Native CLI, React Native version >= 0.71.x and yarn v3

1. Environment setup

Make sure you have correct environment setup on your development machine.

2. Create test project

To bootstrap the project run:

npx react-native init SampleApp

After project creation, follow Yarn migration to version 3 (choose nodeLinker: node-modules option) and at the end, run yarn to reinstall packages

4. Module resolver plugin

Install and configure babel-plugin-module-resolver:

yarn add -D babel-plugin-module-resolver

This will allow you to map imports to specified directories with nice aliases.

babel.config.js
module.exports = {
presets: [ 'module:metro-react-native-babel-preset' ],
+ plugins: [
+ [
+ 'module-resolver',
+ {
+ root: [ './' ],
+ extensions: [
+ '.ios.js',
+ '.ios.ts',
+ '.ios.tsx',
+ '.android.js',
+ '.android.ts',
+ '.android.tsx',
+ '.js',
+ '.ts',
+ '.tsx',
+ '.json',
+ ],
+ },
+ ],
+ ],
};
info

JS Snippets in this tutorial, will use React 18 JSX transform; if you want to use it, add following configuration to babel.config.js:

babel.config.js
module.exports = {
presets: [ 'module:metro-react-native-babel-preset' ],
plugins: [
[
'module-resolver',
{
root: [ './' ],
extensions: [
'.ios.js',
'.ios.ts',
'.ios.tsx',
'.android.js',
'.android.ts',
'.android.tsx',
'.js',
'.ts',
'.tsx',
'.json',
],
},
],
+ [
+ '@babel/plugin-transform-react-jsx',
+ {
+ runtime: 'automatic',
+ },
+ ],
],
};

5. Add following scripts to app's package.json

package.json
{
"name": "rnbridgingtutorial",
"version": "0.0.1",
"private": true,
"scripts": {
- "android": "react-native run-android",
+ "android": "react-native run-android --active-arch-only",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
+ "codegen:android": "./android/gradlew -p android generateCodegenArtifactsFromSchema",
+ "codegen:ios": "node node_modules/react-native/scripts/generate-codegen-artifacts.js --path . --targetPlatform ios --outputPath ./ios"
},
}

First change to "android" command is decreasing build times on Android - it will only build for CPU architecture of the connected device/emulator that you will use for development.

Those other commands - "codegen:android" & "codegen:ios" - are commands that invoke React Native Codegen and generate specification for your native code. Notice that Codegen requires the New Architecture enabled. We will enable it in the next steps.

6. If you are going to use Kotlin for Android development, add Kotlin to your test project, otherwise skip this step

android/build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext {
buildToolsVersion = "33.0.0"
minSdkVersion = 21
compileSdkVersion = 33
targetSdkVersion = 33
+ kotlinVersion = "1.6.10"

// We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
ndkVersion = "23.1.7779620"
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.3.1")
classpath("com.facebook.react:react-native-gradle-plugin")
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
}
android/app/build.gradle
apply plugin: "com.android.application"
+apply plugin: "kotlin-android"
apply plugin: "com.facebook.react"

import com.android.build.OutputFile

// ...

After that, verify if everything works by building your project

yarn android

7. Switch the app to "New Architecture"

"New Architecture" is the future and that's why it will be used throughout this tutorial. Guides will showcase how to write code that supports both old and new arch. However, because new arch setups are more complex, you'll benefit from testing the native code you wrote with TurboModules and Fabric and the backward compatibility layer will make it work on the old architecture.

Since the new architecture is developing dynamically and the instructions for this step are changing often, follow the official React Native New-architecture-app-intro.

After that, verify if everything works by building your project

yarn ios
yarn android

After you build and run the app when Metro serves the JavaScript bundle, you should see "fabric": true in the Metro logs:

BUNDLE ./App.tsx
LOG Running "App" with {"fabric":true,"initialProps":{"concurrentRoot": "true"},"rootTag":1}

8. [OPTIONAL] Navigation setup

If you want to use the same app for different guides, you'll likely need some navigation to navigate between them - use the navigation library of your choice, just make sure it supports "New Architecture"

Cool, with your "playground" ready, let's start the journey!