How to Integrate React Native with Existing Apps?

How to integrate React Native With Existing Apps

Integrating React Native into an existing app is a great way to enhance your mobile features without starting from scratch. This approach lets you combine native and React Native components, speeding up development and improving user experience across platforms.

Many companies rely on professional React Native developers to merge new functionality smoothly into their current apps. This helps save time and reduces costly rewrites.

In this blog, we’ll break down how to integrate React Native with both Android and iOS apps, giving you a clear roadmap to upgrade your app efficiently and effectively. So, let’s begin!

Why Integrate React Native into an Existing App?

Integrating React Native into an existing app lets you modernize without starting from scratch. It’s a practical way to add new features faster, share code across platforms, and improve development efficiency. Here’s why this approach makes sense for many teams and projects.

  • Incremental Adoption: You don’t have to rebuild your entire app. You can start small – maybe a new screen or feature – and slowly expand.
  • Faster Development: React Native lets you build and update UI components faster. You also write code once and use it across Android and iOS.
  • Modern Developer Experience: Enjoy hot reloading, a strong developer community, and access to rich React libraries and UI frameworks.
  • Cross-Platform Consistency: Adding shared features like a login screen, chat, or onboarding? React Native helps you maintain consistent behavior and appearance across platforms.
  • Cost Efficiency: Fewer engineers are needed when you can write a single codebase for multiple platforms.

This approach is especially great for large teams maintaining legacy code-you keep what works and modernize only what’s needed.

React Native Integration with Existing Android Apps

Integrating React Native into an existing Android app can boost development efficiency, bring in cross-platform flexibility, and extend your app’s capabilities with a modern JavaScript-based UI.

To begin, we recommend checking out the React Native Community Template. It provides a clean and minimal Android app structure tailored for integration, helping you grasp how React Native works inside a native setup.

Here is a step-by-step process for embedding React Native into your Android app without disrupting your current structure.

Prerequisites Before You Begin

Before jumping in, make sure your environment is ready for React Native Android development. You can refer to the official React Native environment setup guide for details.

Also, it’s important to have some hands-on knowledge of Android development like creating Activities or editing the AndroidManifest.xml to follow along confidently.

Set Up the Directory Structure

A well-structured directory layout makes integration easier. Create a new folder as the root of your React Native project and place your existing Android app inside the /android subfolder.

This clean separation keeps native and React Native code organized, reducing confusion down the road.

Install NPM Dependencies

Now, let’s get the JavaScript dependencies in place.

Fetch package.json

Navigate to your project’s root and download the template’s package.json using:

curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.75-stable/template/package.json

This file lists all the required libraries needed for your React Native app.

Install Packages

Then, install the dependencies using the following:

npm install //using npm

Or

yarn install //using yarn

This will generate the node_modules/ directory, which holds all required libraries. Don’t forget to update your .gitignore to exclude node_modules/; you can copy it from the Community template if needed.

Configure Gradle Files

Gradle is responsible for managing dependencies and building configurations. You’ll need to update multiple Gradle files to link React Native properly.

Edit settings.gradle

Open your settings.gradle and add the lines provided by the template. These lines initialize the React Native plugin and set up auto-linking:

pluginManagement {
  includeBuild("../node_modules/@react-native/gradle-plugin")
}
plugins {
  id("com.facebook.react.settings")
}
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
includeBuild("../node_modules/@react-native/gradle-plugin")

If you’re using Kotlin DSL, use the .gradle.kts format instead.

Update Top-Level build.gradle 

Add the following snippet inside buildscript to bring in React Native’s Gradle plugin:

buildscript {
  repositories {
    google()
    mavenCentral()
  }
  dependencies {
    classpath("com.android.tools.build:gradle:7.3.1")
    classpath("com.facebook.react:react-native-gradle-plugin")
  }
}

This makes sure the React Native Gradle plugin is recognized by the build system.

Modify App-Level build.gradle

Now open the build.gradle inside your app folder and apply the necessary plugins and dependencies:

apply plugin: "com.android.application"
apply plugin: "com.facebook.react"
repositories {
  mavenCentral()
}
dependencies {
  implementation("com.facebook.react:react-android")
  implementation("com.facebook.react:hermes-android")
}
react {
  autolinkLibrariesWithApp()
}

React Native’s plugin handles library linking and version management, so you don’t have to specify versions manually.

Update gradle.properties

Finally, open your gradle.properties and add:

reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
newArchEnabled=true
hermesEnabled=true

These flags enable the new architecture and Hermes engine to perform better.

Configure Your AndroidManifest.xml

Now it’s time to update your AndroidManifest.xml to ensure network permissions and local development support are enabled.

Add Internet Permission

React Native apps need Internet access to fetch JavaScript bundles during development:

<uses-permission android:name="android.permission.INTERNET" />

Place it inside the <manifest> tag.

Allow Cleartext Traffic for Development

Edit your debug manifest to allow HTTP connections to the Metro bundler:

<application
  android:usesCleartextTraffic="true"
  tools:targetApi="28" />

Make sure this is only in your debug variant to avoid production issues.

Write the TypeScript Code

Now that the native side is ready, let’s build the React Native UI that you’ll integrate into your app.

Create an index.js File

This file is the main entry point for your React Native app:

import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);

It registers your root component so it can be rendered inside your native app.

Create an App.tsx File

Now, write your main React Native component using TypeScript and JSX:

function App(): React.JSX.Element {
  ...
}

This file defines what the React-powered screen looks like and includes reusable components and styles.

Integrate with Your Android Native Code

To render the React Native screen inside your Android app, you’ll update your native classes.

Update Your Application Class

This step sets up React Native during app startup and configures key settings.

JAVA Version

You’ll override the ReactNativeHost and initialize SoLoader in the onCreate() method.

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 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();
   }
  }
}

Kotlin Version

It is the same as Java but tailored to Kotlin syntax with overrides and configuration flags for Hermes and architecture.

// 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
import com.facebook.react.soloader.OpenSourceMergedSoMapping
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, OpenSourceMergedSoMapping)
   if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
     load()
   }
  }
}

As usual, refer to the MainApplication.kt file from the Community template for further reference.

Creating a New ReactActivity

Next, create a new Activity that extends ReactActivity to host the React Native code. This activity will be responsible for starting the React Native runtime and rendering the React component.

Java Version

Extend ReactActivity, provide the component name (HelloWorld), and initialize the delegate.

// 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());
    }
}

Kotlin Version

Same logic as Java, just using Kotlin’s syntax.

// 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)
}

As usual, refer to the MainActivity.kt file from the Community template for Kotlin implementation.

Whenever you create a new Activity, don’t forget to add it to your AndroidManifest.xml. Additionally, set the theme of MyReactActivity to Theme.AppCompat.Light.NoActionBar (or any theme without an ActionBar) to prevent an ActionBar from being rendered on top of your React Native screen. Here’s how to modify the AndroidManifest.xml:

<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>

Now your activity is set up to execute JavaScript code.

Test Your Integration

You have now completed the necessary steps to integrate React Native into your application. The next step is to start the Metro bundler, which will compile your TypeScript application code into a bundle. Metro’s HTTP server will serve this bundle from localhost to your simulator or device, enabling hot reloading.

First, create a metro.config.js file in the root of your project with the following content:

const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);

You can refer to the metro.config.js file from the Community template for guidance. Once the config file is set up, you can start the bundler. Run the following command in your project’s root directory:

npm start
Or 
yarn start

Now, build and run your Android app as you normally would. When you navigate to your React-powered Activity within the app, it should load the JavaScript code from the development server and display:

Creating a Release Build in Android Studio

You can also use Android Studio to generate release builds, just like you would for a native Android app. The React Native Gradle Plugin will automatically bundle the JavaScript code into your APK/App Bundle.

If you’re not using Android Studio, you can create a release build with the following commands:

cd android
# For a Release APK
./gradlew :app:assembleRelease
# For a Release AAB
./gradlew :app:bundleRelease
Want to Launch Your App on Both iOS and Android? We Can Help

React Native Integration with Existing iOS Apps

If you already have an iOS app and want to add some React Native screens or modules, it’s possible to embed React Native into your existing native app. Here’s how to do it using TypeScript and the React Native Community template:

Prerequisites

Before starting, follow the guide to set up your development environment and configure React Native for iOS without a framework. The guide assumes you have a basic understanding of iOS development, including tasks like creating a UIViewController and modifying the Podfile.

Set Up the Directory Structure

To ensure a smooth setup, create a new folder for your integrated React Native project. Then, move your existing iOS project into the /ios subfolder.

Install NPM Dependencies

Navigate to the root directory and run the following command:

curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.78-stable/template/package.json

This command will fetch the package.json file from the Community template and add it to your project. Next, install the NPM dependencies by running:

npm install
Or 
yarn install // Using yarn

This process will create a new node_modules folder containing all the JavaScript dependencies needed to build your project.

Don’t forget to add node_modules/ to your .gitignore file (use the default .gitignore file from the Community template).

Install Development Tools

Here are some development tools you need to install:

  • Command Line Tools for Xcode: You need to install the Command Line Tools for Xcode. To do this, go to the Settings (or Preferences) in the Xcode menu. Navigate to the Locations panel and select the latest version from the Command Line Tools dropdown to install the tools.
  • CocoaPods: CocoaPods is a package management tool for iOS and macOS development. It’s used to add the React Native framework code into your project locally.

We recommend installing CocoaPods through Homebrew with the following command:

brew install cocoapods

Add React Native to Your App

To set up CocoaPods, we need two essential files:

  • Gemfile: Defines the required Ruby dependencies.
  • Podfile: Specifies how to install the necessary dependencies.

For the Gemfile, go to the root directory of your project and run the following command:

curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.78-stable/template/Gemfile

This command will download the Gemfile from the template.

Note:  If you created your project using Xcode 16, update your Gemfile with the following:

gem ‘cocoapods’, ‘1.16.2’

gem ‘activesupport’, ‘>= 6.1.7.5’, ‘!= 7.1.0’

gem ‘xcodeproj’, ‘1.27.0’

Xcode 16 generates projects differently than earlier versions, so you’ll need the latest versions of CocoaPods and Xcodeproj gems for compatibility. For the Podfile, navigate to the iOS folder of your project and execute:

curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.78-stable/template/ios/Podfile

Make sure to refer to the Community Template for the Gemfile and Podfile. Don’t forget to modify this line.

Next, run the following commands in the ios folder to install the Ruby gems and CocoaPods:

bundle install
bundle exec pod install

The first command installs the Ruby dependencies, and the second integrates the React Native code into your app, allowing your iOS files to import the necessary React Native headers.

Write the TypeScript Code

At this stage, we’ll modify the native iOS application to integrate React Native. The first step is to write the actual React Native code for the new screen we’ll be adding to our application.

Create an index.js File

Begin by creating an empty index.js file in the root directory of your React Native project. The index.js file is a mandatory entry point for React Native applications. It can either be a small file that imports other components of your React Native app or contain all the required code directly.

Your index.js file should look like this (using the Community template as reference):

import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);

Create an App.tsx File

Now, let’s create an App.tsx file. This is a TypeScript file that supports JSX expressions. It will contain the root React Native component, which we will integrate into the iOS application:

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;

Use the Community template file as a reference for your setup.

Integrate with Your iOS Native Code

Next, we need to add some native code to initialize the React Native runtime and enable it to render our React components.

Requirements

React Native initialization is no longer tied to a specific part of an iOS app. It can now be initialized using a class called RCTReactNativeFactory, which handles the React Native lifecycle for you.

Once the class is initialized, you can either start a React Native view with a UIWindow object, or ask the factory to generate a UIView, which can be loaded into any UIViewController. In this example, we’ll create a ViewController that loads a React Native view as its content.

Create the ReactViewController

Start by creating a new file using the Cocoa Touch Class template (⌘N). Make sure to select UIViewController as the “Subclass of” option. Then, open the ReactViewController.m file and modify it as follows:

Here is the ObjectiveC version:

@interface ReactViewController ()
@end
@interface ReactNativeFactoryDelegate: RCTDefaultReactNativeFactoryDelegate
@end
@implementation ReactViewController {
  RCTReactNativeFactory *_factory;
  id<RCTReactNativeFactoryDelegate> _factoryDelegate;
}
     [super viewDidLoad];
     // Do any additional setup after loading the view.
    _factoryDelegate = [ReactNativeFactoryDelegate new];
    _factoryDelegate.dependencyProvider = [RCTAppDependencyProvider new];
    _factory = [[RCTReactNativeFactory alloc] initWithDelegate:_factoryDelegate];
    self.view = [_factory.rootViewFactory viewWithModuleName:@"HelloWorld"];
 }
@end
@implementation ReactNativeFactoryDelegate
(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
Here is the Swift version:
import UIKit
import React
import React_RCTAppDelegate
import ReactAppDependencyProvider
class ReactViewController: UIViewController {
  var reactNativeFactory: RCTReactNativeFactory?
  var reactNativeFactoryDelegate: RCTReactNativeFactoryDelegate?
  override func viewDidLoad() {
    super.viewDidLoad()
    reactNativeFactoryDelegate = ReactNativeDelegate()
    reactNativeFactoryDelegate!.dependencyProvider = RCTAppDependencyProvider()
    reactNativeFactory = RCTReactNativeFactory(delegate: reactNativeFactoryDelegate!)
    view = reactNativeFactory!.rootViewFactory.view(withModuleName: "HelloWorld")
  }
}
class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
    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
    }
}

Presenting a React Native View in the rootViewController

Now, we need to display the React Native view. To do this, we’ll create a new ViewController that will host the view, which can then load the JavaScript content. We’ll assume you have an existing ViewController and make it present the ReactViewController when triggered. For this example, we’ll use a button to present React Native modally.

Update the ViewController.m file as follows:

@interface ViewController ()
@end
@implementation ViewController {
  ReactViewController *reactViewController;
}
   [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];
}
@end

Here is the Swift version:

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
      guard let self else { return }
      if reactViewController == nil {
       reactViewController = ReactViewController()
      }
      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),
    ])
  }
}

Additional Configuration

To enable seamless switching between the Debug and Release versions of the Hermes engine that React Native uses, ensure you disable the sandbox scripting feature. In Xcode, click on your app, go to Build Settings, search for “script,” and set User Script Sandboxing to NO.

Additionally, make sure to add the UIViewControllerBasedStatusBarAppearance key in your Info.plist file with a value of NO.

Test Your Integration

You’ve now completed the essential steps to integrate React Native with your application. The next task is to start the Metro bundler to compile your TypeScript application code into a bundle. The Metro bundler’s HTTP server will share the bundle from localhost on your development environment to a simulator or device, enabling hot reloading.

Create the metro.config.js File

First, create a metro.config.js file in the root of your project with the following content:

const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);

You can refer to the metro.config.js file from the Community template as an example.

Create the .watchmanconfig File

Next, create a .watchmanconfig file in the root of your project with the following command:

echo {} > .watchmanconfig

Once these configuration files are in place, you can start the bundler. Run the following command in the root directory of your project:

npm start
Or
yarn start

Build and Run Your iOS App

Now, build and run your iOS app as you would normally. When you navigate to the React-powered Activity inside your app, it should fetch and display the JavaScript code from the development server.

Creating a Release Build in Xcode

You can also use Xcode to create release builds. The only extra step is to add a script that runs during the build process to package your JavaScript and images into the iOS application. To do this in Xcode:

  1. Select your application.
  2. Click on Build Phases.
  3. Click the button in the top-left corner and select New Run Script Phase.
  4. Rename the new script to Bundle React Native code and images.
  5. Paste the following script into the text box:
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"

Drag and drop the script before the [CP] Embed Pods Frameworks script. Now, when you build your app for release, everything should function as expected.

Passing Initial Props to the React Native View

In some scenarios, you may want to send data from the Native app to JavaScript. For instance, you might need to pass the user ID of the currently logged-in user along with a token used to fetch data from a database.

This can be achieved using the initialProperties parameter in the view(withModuleName:initialProperties) method of the RCTReactNativeFactory class. Here’s how you can do it:

  1. Update the App.tsx file to read the initial properties.
  2. Open the App.tsx file and modify it to accept the initial properties as follows:
import {
  Colors,
  DebugInstructions,
  Header,
  ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
function App(props): 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 />
         <Text style={styles.title}>UserID: {props.userID}</Text>
         <Text style={styles.title}>Token: {props.token}</Text>
        </View>
      </ScrollView>
    </SafeAreaView>
  );
}
const styles = StyleSheet.create({
  title: {
    fontSize: 24,
    fontWeight: '600',
   marginLeft: 20,
  },
  bold: {
    fontWeight: '700',
  },
});
export default App;

These changes make the App component accept properties. The RCTReactNativeFactory will automatically pass these properties to the component when they are rendered.

Next, update the ReactViewController.mm file to pass the initial properties to JavaScript.

[super viewDidLoad];
   // Do any additional setup after loading the view.
   _factoryDelegate = [ReactNativeFactoryDelegate new];
   _factoryDelegate.dependencyProvider = [RCTAppDependencyProvider new];
   _factory = [[RCTReactNativeFactory alloc] initWithDelegate:_factoryDelegate];
  self.view = [_factory.rootViewFactory viewWithModuleName:@"HelloWorld" initialProperties:@{
    @"userID": @"12345678",
    @"token": @"secretToken"
  }];
}

Now, when you run the app again, you should see the following screen once you present the ReactViewController.

Let’s Build a High-Performance App with React Native!

FAQs on Integrating React Native with Existing Apps

Can you make iOS apps with React Native?

Yes, React Native lets you build fully functional iOS apps using JavaScript and React. It compiles native code and supports native modules.

Can you use React Native for apps?

Yes, React Native is used to build cross-platform mobile apps for both iOS and Android using a single codebase.

How to integrate Android SDK with React Native?

To integrate Android SDK with React Native, install Android Studio, set up the Android SDK, and update your local.properties file with the SDK path. Then, use npx react-native run-android to build the app.

Can I use React Native for iOS apps?

Yes, you can build and run iOS apps using React Native. You’ll need a Mac with Xcode to build and test the iOS version.

How to convert React Native app to iOS?

If your app is built with React Native, it already supports iOS. Just open the iOS folder in Xcode, install pods, and run the app using npx react-native run-ios.

Conclusion

React Native makes it easier for developers to build cross-platform apps without learning Swift or Kotlin separately. With a single JavaScript codebase, you can deploy to both iOS and Android, which saves time and effort.

For iOS development, React Native supports native modules, Swift/Objective-C integrations, and smooth performance. You’ll need Xcode on a Mac to run and test your iOS builds, but the process is well-documented and beginner-friendly.

Whether you’re starting a new project or migrating an existing one, React Native is a solid choice for mobile app development. If you want to build advanced functionalities or ensure smooth integration with your existing app, consulting a React Native app development agency will be the perfect decision.

author
Shah Vish Shah is Technical Consultant at WPWeb Infotech since 2015. He has vast experience in working with various industries across the globe. He writes about the latest web development technologies and shares his thoughts regularly.