Mobile Development 14 min read

Seamlessly Integrate React Native Modules into Existing Native Apps with Pegasus

This article explains how to embed React Native components into an existing iOS/Android app by turning the RN module into a native library called Pegasus, covering integration steps, architecture, and bidirectional communication between JavaScript and native code.

Baixing.com Technical Team
Baixing.com Technical Team
Baixing.com Technical Team
Seamlessly Integrate React Native Modules into Existing Native Apps with Pegasus

We wrapped a React Native component with a

UIViewController

(iOS) or

Activity

(Android) as the first step to integrate Pegasus into the Baixing main app. This article details Pegasus’s design and implementation, focusing on two questions: how to integrate Pegasus into an existing native project and how to handle communication between RN and native.

Integration

Integrating an RN module into an existing app generally follows these steps (see React Native docs):

Create RN dependencies and directory structure.

Write your component in JavaScript.

Install RN packages via NPM/Yarn and native dependencies via CocoaPods (iOS) or Gradle (Android).

Add

RCTRootView

(iOS) or

ReactRootView

(Android) to the app as a container for the RN component.

Test and verify the code.

Bundle the JavaScript.

These steps require a local RN development environment (Node, NPM, etc.), which can be burdensome for native‑only developers.

<code>npm install
npm run start
</code>

To avoid polluting the native toolchain, we propose turning Pegasus into a native library distributed via CocoaPods (iOS) or Gradle (Android). For iOS, adding a single line to

Podfile

pulls in Pegasus:

<code>pod 'Pegasus'
</code>

In native code, a simple initialization launches an RN page:

<code>// Initialize Pegasus
Pegasus *pegasus = [[Pegasus alloc] init];

// Create RN component container
PEGComponentViewController *viewController = [PEGComponentViewController alloc] initWithPegasus:pegasus
    moduleName:@"Profile"
    initialProperties:@{ @"name" : "Jack" }];
[self.navigationController pushViewController:viewController animated:YES];
</code>

Pegasus’s architecture is illustrated below:

Externally Pegasus appears in three forms:

An NPM package (JavaScript).

A CocoaPod for iOS.

A Gradle dependency for Android.

Internally it consists of four layers:

Native UI Components and Module APIs – custom native UI and APIs that supplement RN’s built‑in components.

JavaScript layer – pure React code handling UI and business logic.

Native Public API – view controllers, activities, and initialization interfaces exposed to the host app.

Cross‑platform shell project – tooling for development and debugging.

For iOS we package the bundled JS, assets, and Objective‑C code into a single CocoaPod:

Key configuration files (trimmed for brevity) are shown below:

<code>// package.json
{
  "name": "pegasus",
  "dependencies": {
    "react": "16.0.0-alpha.12",
    "react-native": "0.46.4",
    "react-native-code-push": "^4.1.0-beta"
  }
}
</code>
<code># Pegasus.podspec
require 'json'

npm_package = JSON.load(File.read(File.expand_path('../package.json', __FILE__)))

Pod::Spec.new do |s|
  s.name         = 'Pegasus'
  s.version      = npm_package['version']
  s.summary      = 'React Native Components used by Baixing.'
  s.source_files = 'ios/Classes/**/*.{h,m}'
  s.resource_bundles = { 'Pegasus' => ['ios/Assets/{Pegasus.js,assets,*.xcassets,*.lproj}'] }
  react_native_version = npm_package['dependencies']['react-native'].sub('^', '~>')
  s.dependency 'React/BatchedBridge', react_native_version
  s.dependency 'React/Core', react_native_version
  # ... other RN dependencies ...
  s.dependency 'CodePush/Core', code_push_version
  s.dependency 'SSZipArchive'
  s.dependency 'MBProgressHUD'
end
</code>

After resolving native dependencies (often requiring a private CocoaPods or Maven repository), we bundle the JavaScript:

<code>// NPM script
"scripts": {
  "bundle-ios": "react-native bundle --platform ios --dev false --entry-file index.ios.js --bundle-output ios/Assets/Pegasus.js --sourcemap-output ios/Assets/Pegasus.js.map --assets-dest ios/Assets"
}
</code>
<code># Run
npm run bundle-ios
</code>

By packaging the RN module as a native library, developers can integrate Pegasus like any other native dependency, without altering their existing toolchain or dealing with JS tooling.

Communication Issues

Two main communication directions need handling:

JS ↔ native.

Module ↔ host app.

JS → Native

Implemented via

NativeModules

and

RCTBridgeModule

. Example:

<code>@interface PEGDataProviderModule : NSObject <RCTBridgeModule>
@end

@implementation PEGDataProviderModule
RCT_EXPORT_MODULE()
RCT_EXPORT_METHOD(getUsername:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
  if (resolve) { resolve(@"Jack"); }
}
@end
</code>

JavaScript side:

<code>import { NativeModules } from 'react-native';
NativeModules.PEGDataProviderModule.getUsername().then(username => console.log(username));
</code>

Native UI components can also be exposed via

RCTViewManager

, allowing JS to render custom native views.

Native → JS

Native code can send events using the event emitter or invoke JS by creating an

RCTRootView

with a module name and initial props:

<code>RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
    moduleName:@"ImageBrowserApp"
    initialProperties:props];
</code>

Pegasus heavily uses this pattern to launch RN components from native code.

JS Page → Native Page

By exposing a router as a bridge module, JS can trigger native navigation via a URL scheme:

<code>@implementation PEGRouterModule
RCT_EXPORT_METHOD(route:(NSURL *)url) {
  [self.router routeURL:url];
}
@end
</code>

This enables seamless transitions between RN screens and native screens while preserving native navigation animations.

Conclusion

The article presented the common JS‑native communication methods that make Pegasus possible, and showed how packaging the RN module as a native library lets existing apps adopt RN capabilities without touching any JavaScript code. Upcoming topics will cover dependency management, development/debugging workflows, and dynamic deployment of RN modules.

iOSAndroidReact Nativenative modulesPegasusmobile integration
Baixing.com Technical Team
Written by

Baixing.com Technical Team

A collection of the Baixing.com tech team's insights and learnings, featuring one weekly technical article worth following.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.