Implementing Native Code in React Native

RMAG news

Hey devs!

React Native is an excellent tool for building mobile applications with a single codebase that can run on both iOS and Android. However, sometimes we need to access platform-specific functionalities that are not available in the standard React Native library. In these situations, we can turn to native code implementations.

In this post, we will explore how to add native functionalities to your React Native application using native packages. We will use the example of a Gallery library, which already has native implementations in Swift for iOS and Kotlin for Android.

Why Use Native Code?

Performance: Native code can be optimized for the specific platform, offering better performance.

Access to Specific APIs: Some functionalities are only available through native APIs.

Integration with Native Libraries: Use of libraries or SDKs that only exist in native form.

Setting Up the Environment

Before we start, make sure you have your environment set up for React Native development, including Xcode for iOS and Android Studio for Android.

Project Structure

Assume we have the following basic structure of a React Native project:

my-react-native-app
├── android
├── ios
├── src
│ ├── components
│ ├── screens
│ ├── App.js
├── package.json

Adding Native Code

Creating the Native Module

Let’s create a native module that exposes gallery functionalities. We’ll start with Android using Kotlin.

Android (Kotlin)

1- Create a new Kotlin module:
Navigate to android/app/src/main/java/com/myreactnativeapp/ and create a new directory gallery.

2- Add the Kotlin class:
Create a GalleryModule.kt file inside the gallery directory:

package com.myreactnativeapp.gallery

import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Promise

class GalleryModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

override fun getName(): String {
return “GalleryModule”
}

@ReactMethod
fun openGallery(promise: Promise) {
// Implementation to open the gallery
promise.resolve(“Gallery opened successfully!”)
}
}

3- Register the module:
In the same directory, create a GalleryPackage.kt file:

package com.myreactnativeapp.gallery

import com.facebook.react.ReactPackage
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
import com.facebook.react.bridge.NativeModule

class GalleryPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(GalleryModule(reactContext))
}

override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}

4- Update MainApplication.java:
Add the new package to the list of registered packages:

import com.myreactnativeapp.gallery.GalleryPackage; // Import the package

@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings(“UnnecessaryLocalVariable”)
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new GalleryPackage()); // Add the new package
return packages;
}

iOS (Swift)

1- Create the Swift module:
Navigate to ios and open the project in Xcode. In ios, create a new Swift file GalleryModule.swift inside the Libraries directory.

import Foundation
import React

@objc(GalleryModule)
class GalleryModule: NSObject {

@objc
func openGallery(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
// Implementation to open the gallery
resolve(“Gallery opened successfully!”)
}
}

2- Update the bridge header:
Open ios/YourProjectName-Bridging-Header.h and add:

#import “React/RCTBridgeModule.h”

3- Register the module:
Open AppDelegate.m and add the module registration:

#import <React/RCTBridge.h>
#import <React/RCTBridgeModule.h>

@implementation AppDelegate

(BOOL)application🙁UIApplication *)application didFinishLaunchingWithOptions🙁NSDictionary *)launchOptions
{
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
[bridge registerModuleForName:@”GalleryModule” withClass:[GalleryModule class]];
// Rest of the code
}

Using the Native Module in React Native

Now that we have our native modules set up, we can use them in our JavaScript code.

1- Create a JavaScript file for the module:

// src/nativeModules/GalleryModule.js
import { NativeModules } from react-native;
const { GalleryModule } = NativeModules;

const openGallery = async () => {
try {
const result = await GalleryModule.openGallery();
console.log(result);
} catch (error) {
console.error(error);
}
};

export { openGallery };

2- Use the module in your component:

// src/screens/GalleryScreen.js
import React from react;
import { View, Button } from react-native;
import { openGallery } from ../nativeModules/GalleryModule;

const GalleryScreen = () => {
return (
<View>
<Button title=Open Gallery onPress={openGallery} />
</View>
);
};

export default GalleryScreen;

Conclusion

Adding native code to your React Native application can seem challenging at first, but with the right steps, you can easily extend your app’s capabilities to include platform-specific functionalities. This guide has shown how to create and integrate simple native modules for both Android and iOS. With this foundation, you can explore further and add complex functionalities as needed.

References

React Native Documentation on Native Modules
React Native Documentation on Integrating with Swift
React Native Documentation on Integrating with Kotlin

This guide should provide a solid foundation for you to start working with native code in React Native. If you have any questions or run into issues, the React Native community is very active and can be an excellent resource for additional support.