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.
Top comments (0)