Table of contents
1.
Introduction
2.
Native Modal Setup
3.
How to build a native module
3.1.
Create a Native Module for Android
3.1.1.
Setup
3.1.2.
Make Your Own Native Module File
3.1.3.
Module Name
3.1.4.
Export a Native Method to JavaScript
3.1.5.
Register the Module
3.2.
Create a Native Module for iOS
3.2.1.
Setup
3.2.2.
Create Custom Native Module Files
3.2.3.
Module Name
3.2.4.
Export a Native Method to JavaScript
4.
Native Modules NPM Package Setup
5.
Frequently Asked Questions
5.1.
What are Native Modules?
5.2.
How can you develop a native module for React Native?
5.3.
Why is TurboReactPackage a better method for registering the native modules in React native?
6.
Conclusion
Last Updated: Mar 27, 2024

Native Modules

Author Avinash Pandey
2 upvotes
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Sometimes an app requires access to a platform API for which React Native does not yet have a module. Perhaps you want to reuse some existing Java code instead of rewriting it in JavaScript or develop some high-performance, multi-threaded code for image processing, a database, or advanced extensions.

React Native is designed so that you can create actual native code while still having access to all of the platform's features. This is a more advanced feature that is unlikely to be included in the standard development process, but it must exist. If React Native doesn't support a native feature, you should be able to create it yourself using Native Modules.

Native Modal Setup

You can develop a native module for your React Native application in one of two ways:

  1. Within the iOS/Android projects of your React Native application directly.
  2. As an NPM package that your/other React Native applications can install as a dependency.

This blog will first show you how to use a native module directly within a React Native application. The native module built in the following guide, on the other hand, can be distributed as an NPM package.

How to build a native module

You require a React Native application to work with as a prerequisite because we will build a native module within a React Native application directly.

Assume you wish to generate calendar events using the iOS/Android native calendar APIs from JavaScript within a React Native application. There is no JavaScript API for communicating with the native calendar libraries in React Native. Native modules, on the other hand, allow you to develop native code that interacts with native calendar APIs. Then, in your React Native application, you can invoke that native code using JavaScript.

Create a Native Module for Android

We'll make a native module called CalendarModule that lets you use JavaScript to access Android's calendar APIs. You will be able to call CalendarModule in the end. createCalendarEvent('Dinner Party,' My House'); invokes a Java/Kotlin method to create a calendar event using JavaScript.

Setup

  • Launch the Android project in Android Studio within your React Native application.
  • Using Android Studio to write your native code is recommended. Android Studio is an IDE for Android development that will assist you in swiftly resolving minor difficulties such as code syntax errors.
  • Enabling Gradle Daemon to speed up builds while iterating on Java/Kotlin code is also recommended.

Make Your Own Native Module File

The first step is to create a Java/Kotlin file in the android/app/src/main/java/com/your-app-name/ folder called (CalendarModule.java or CalendarModule.kt). This Java/Kotlin file will include the Java/Kotlin class for your native module.

Then add the following code segment:

Java:
package com.your-app-name; // replace com.your-app-name with your app’s name
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.Map;
import java.util.HashMap;

public class CalendarModule extends ReactContextBaseJavaModule {
  CalendarModule(ReactApplicationContext context) {
      super(context);
  }}
You can also try this code with Online Java Compiler
Run Code

 

Kotlin:
package com.your-app-name // replace com.your-app-name with your app’s name
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod

class CalendarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {...}

 

Your CalendarModule class extends the ReactContextBaseJavaModule class, as you can see. Native Java/Kotlin modules for Android are built as classes that extend ReactContextBaseJavaModule and implement the JavaScript functionality.

Module Name

The getName() method must be implemented by all Java/Kotlin native modules in Android. This method returns a string that represents the native module's name. The native module's name can then be used to access it in JavaScript. getName(), for example, returns "CalendarModule" in the code sample below.

Java Kotlin
// add to CalendarModule.java
@Override
public String getName() {
  return "CalendarModule";
}
You can also try this code with Online Java Compiler
Run Code
// add to CalendarModule.kt
override fun getName() = "CalendarModule"

 

The native module can then be accessed in JavaScript like this:

const { CalendarModule } = ReactNative.NativeModules;
You can also try this code with Online Javascript Compiler
Run Code

Export a Native Method to JavaScript

The next step is to add a method to your native module that creates calendar events and can be called from JavaScript. @ReactMethod must be annotated on any native module methods called from JavaScript.

Set up a method createCalendarEvent() for CalendarModule that can be invoked in JavaScript through CalendarModule. For the time being, the method will accept names and locations as strings. The various argument types will be discussed shortly.

Java Kotlin
@ReactMethod
public void createCalendarEvent(String name, String location) {
}
You can also try this code with Online Java Compiler
Run Code
@ReactMethod fun createCalendarEvent(name: String, location: String) {}

 

When you call the method from your application, add a debug log to prove it was called. The Log class from the Android util package can be imported and used in the following way:

Java Kotlin
import android.util.Log;

@ReactMethod
public void createCalendarEvent(String name, String location) {
  Log.d("CalendarModule", "Create event called with name: " + name
  + " and location: " + location);
}
You can also try this code with Online Java Compiler
Run Code
import android.util.Log

@ReactMethod
fun createCalendarEvent(name: String, location: String) {
   Log.d("CalendarModule", "Create event called with name: $name and location: $location")
}

 

Register the Module

After writing a native module, it must be registered with React Native. To do so, create a ReactPackage with your native module and register the ReactPackage with React Native. React Native will loop through all packages during initialization and register each native module within each ReactPackage.

To receive a list of native modules to register, React Native calls the method createNativeModules() on a ReactPackage. A JavaScript module will not be available if it is not instantiated and returned in createNativeModules for Android.

Create a new Java/Kotlin Class named (MyAppPackage.java or MyAppPackage.kt) that implements ReactPackage in the android/app/src/main/java/com/your-app-name/ folder to add your Native Module to ReactPackage:

Then add the following code segment:

Java:
package com.your-app-name; // replace your-app-name with your app’s name
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyAppPackage implements ReactPackage {
  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
      return Collections.emptyList();
  }
  @Override
  public List<NativeModule> createNativeModules(
          ReactApplicationContext reactContext) {
      List<NativeModule> modules = new ArrayList<>();
      modules.add(new CalendarModule(reactContext));
      return modules;
  }
}
You can also try this code with Online Java Compiler
Run Code

 

Kotlin:
package com.your-app-name // replace your-app-name with your app’s name
import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager
class MyAppPackage : ReactPackage {
   override fun createViewManagers(
       reactContext: ReactApplicationContext
   ): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()
   override fun createNativeModules(
       reactContext: ReactApplicationContext
   ): MutableList<NativeModule> = listOf(CalendarModule(reactContext)).toMutableList()
}

 

This file imports the native module CalendarModule that you created. It then instantiates CalendarModule within the createNativeModules() function and returns it as a list of NativeModules to register. You can also instantiate and add more native modules to the list returned here if you add them later.

Note: It's worth noting that this method of registering native modules immediately initializes all native modules when the app starts, which increases the app's startup time. As an alternative, you can try TurboReactPackage. TurboReactPackage implements a getModule(String name, ReactApplicationContext rac) method that produces the native module object as required, rather than createNativeModules, which returns a list of instantiated native module objects.

 

You must add MyAppPackage to the list of packages returned by ReactNativeHost's getPackages() method to register the CalendarModule package. Open your MainApplication.java or MainApplication.kt file, which is located in the android/app/src/main/java/com/your-app-name/ directory.

Java Kotlin
@Override
 protected List<ReactPackage> getPackages() {
   @SuppressWarnings("UnnecessaryLocalVariable")
   List<ReactPackage> packages = new PackageList(this).getPackages();
   // below MyAppPackage is added to the list of packages returned
   packages.add(new MyAppPackage());
   return packages;
 }
You can also try this code with Online Java Compiler
Run Code
override fun getPackages(): List<ReactPackage> =
   PackageList(this).packages.apply {
       // Packages that cannot be autolinked yet can be added manually here, for example:
       // packages.add(new MyReactNativePackage());
       add(MyAppPackage())
   }

You have now successfully registered your native module for Android!

Create a Native Module for iOS

We'll make a native module called CalendarModule that lets you use JavaScript to access Apple's calendar APIs. You will be able to call CalendarModule in the end. createCalendarEvent('Dinner Party,' My House'); invokes a native method to create a calendar event using JavaScript.

Setup

  • Launch the iOS project in Xcode within your React Native application.
  • We recommend using Xcode to write your native code. Xcode is built for iOS development that will assist you in swiftly resolving minor difficulties such as code syntax errors.

Create Custom Native Module Files

The first step is to create the header and implementation files for our primary custom native module. Create a new RCTCalendarModule.h file and add the following code to it:

//  RCTCalendarModule.h
#import <React/RCTBridgeModule.h>
@interface RCTCalendarModule : NSObject <RCTBridgeModule>
@end

As you can see, the CalendarModule class implements the RCTBridgeModule protocol. A native module is an Objective-C class that implements the RCTBridgeModule protocol.

Next up, Let's get started with the native module now. Create the RCTCalendarModule.m implementation file in the same folder and contain the following content:

// RCTCalendarModule.m
#import "RCTCalendarModule.h"
@implementation RCTCalendarModule
// To export a module named RCTCalendarModule
RCT_EXPORT_MODULE();
@end

Module Name

Your RCTCalendarModule.m native module now just has the RCT_EXPORT_MODULE macro, which exports and registers the native module class with React Native. The optional input to the RCT_EXPORT_MODULE macro is the module's name available in your JavaScript code.

In JavaScript, the native module can then be accessed as follows:

const { CalendarModuleFoo } = ReactNative.NativeModules;
You can also try this code with Online Javascript Compiler
Run Code

 

If you don't provide the JavaScript module a name, it will be the same as the Objective-C class name, excluding any "RCT" or "RK" prefixes. As seen below, let's try calling RCT_EXPORT_MODULE without any arguments. As a result, React Native will see the module as CalendarModule, but instead of RCT because that is the Objective-C class name.

// Without passing in a name, this will export the native module name as the Objective-C class name with "RCT" removed
RCT_EXPORT_MODULE();

 

In JavaScript, the native module can then be accessed as follows:

const { CalendarModule } = ReactNative.NativeModules;
You can also try this code with Online Javascript Compiler
Run Code

Export a Native Method to JavaScript

React Native will not expose any native module methods to JavaScript unless explicitly instructed. The RCT_EXPORT_METHOD macro can be used to accomplish this. The return type of methods written in the RCT_EXPORT_METHOD macro is always void because they are asynchronous.

Let's use the RCT_EXPORT_METHOD macro to create a native method for our CalendarModule native module. Call it createCalendarEvent() and pass in string arguments for the name and location.

RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location)
{
}

 

Before expanding its functionality, add a console log to the createCalendarEvent() method to ensure it was invoked from JavaScript in your React Native application. React's RCTLog APIs can be used. Let's add the log call after importing that header at the start of your file.

#import <React/RCTLog.h>
RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location)
{
RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
}

You have now successfully created your native module for iOS!

Native Modules NPM Package Setup

Native modules are often delivered as npm packages, except that they will include some native code per platform and the regular JavaScript. This guide may help you learn more about npm packages.

We'll utilize the community tool create-react-native-library to put up the basic project structure for a native module. You can dig deeper into how that library works if you like, but for our purposes, we'll just run the following script:

$ npm install -g react-native-create-library
$ react-native-create-library MyLibrary

 

Where MyLibrary is the name of the new module, you want. After that, go to the MyLibrary folder and install the npm package so that it is available locally on your system:

$ npm install

After that, navigate to your main react app folder (which you created by doing react-native init MyApp)

Add your newly built module to your package.json as a dependency. To install it from your local npm repository, use npm install.

When all steps above are done, you will be able to continue with Android Native Modules or iOS Native Modules guides to add in some code.

Frequently Asked Questions

What are Native Modules?

A native module is a collection of JavaScript functions implemented into each platform natively (in our case, iOS and Android). It's used when native capabilities are required, but there isn't currently a corresponding module for React Native.

How can you develop a native module for React Native?

You can develop a native module for your React Native application in one of two ways:

  1. Within the iOS/Android projects of your React Native application directly.
  2. As an NPM package that your/other React Native applications can install as a dependency.

Why is TurboReactPackage a better method for registering the native modules in React native?

TurboReactPackage implements a getModule(String name, ReactApplicationContext) method that produces the native module object as required, rather than createNativeModules, which initializes all native modules when the app starts, which increases the app's startup time.

Conclusion

In this blog, we have learned about Native Modules, their setup, and how to build a native module in Android and iOS. Refer to  Android Native Modules or iOS Native Modules guides for more information.

I hope you have enjoyed reading this blog.

Live masterclass