Practice React Native: Creating your own Native Module

ナーム Nam Nguyen
6 min readDec 2, 2018

Sometime when we need a specific way to interact with the phone or operator system which is various different between iOS and Android, that when we need to lean that responsibility to the OS it self.

In RN, most of the logic and UI, in the best way, must be consistent between platforms. So, In an advance level of bringing best user experience to end user, we need to create native module, that mean the leaning the logic to the Native Part. There are ton of article out there showing why and when we need to create a native module, I won’t dive into explanation again. Instead, I will show you how can we create a native module that could be used in React native code. That mean, you write your Objective-C/Java code, and import and run it as a module in Javascript Code.

I will show you here the most basic way to create the most basic library, called: open https://google.com. It means, I want to open Google by using the default iOS/Android browser in a native way.

Creating react-native-browser.

First, we need to have the development environment ready for working in react-native. I suppose that you have npm, node, react-native-cli, VSCode, yarn, XCode, Android-Studio, Chrome, iOS Simulator, Android Emulator installed.

Recommended: You should check if you have Java 1.7+ installed. The best version I experienced that works perfectly for React Native development is Java 1.8. Open your Terminal:
brew tap caskroom/versions
brew cask install java8

Install react-native-create-library

The most convenient way is using react-native-create-library to create a dependency that could be imported in React Native. You can install it as a global dependency by using npm install -g react-natice-create-library.

Create dependency name browser

After installed react-native-library successfully, now, it’s time to create our first dependency. react-native-create-library browser --package-identifier com.mylibs --platform ios,android

After that, you will see that we have a new folder called browser which is the dependency that just created.

To be consistent, or, in another call, to be easy to identify your library when you need to publish it to npm registry and allow the community to use, we should rename it to react-native-browser
mv browser ./react-native-browser

After creating our dependency called browser we have a structured folder:

tree is a library I use to print a folder structure in terminal. you also can install it by using HomeBrew:
brew install tree

When create new library by using react-native-create-library, there was a parameter called --platform, default value is ios,android,windows, means if you don't provide which platforms you want our dependency to support, it will generate 3 folders for iOS, Android, Windows. Since we don't support Windows in this demo, I will remove the windows folder.

cd react-native-browser

rm -rf windows

Analyse dependency folder

Basically, Javascript communicate with our module via a bridge, so, it have no idea about our native code. The concept is that the developers who will use our library will lean on what we define/export/allow them to call. If you can see in our folder, there is a javascript file named index.js. Let take a look into that file.

The responsibility of index.js is export public functions for another developer to use it in their project. We need to call our NativeModules here and export it out. Sounds like a bridge, or a wrapper exactly.

cat is used to print out the content of a file, in text.
cat index.js will print index.js out right in the terminal.

As we see, the purpose of index.js just export our Module as default, nothing else. But in best practise, we usually do another thing in index.js as a convenient wrapper specified for each platform, so, better we provide different module.exports .

Add your new Module in to project

Before we continue writing our own code in the native module, I recommend you link it in to project, it’s easier for us to code in a compile-able project rather than typing without any awareness.

Copy your library folder react-native-browser into node_modules. Link your current module to react-native NativeModules by using react-native link react-native-browser

Then, we will continue editing our Module in node_modules/react-native-browser/ios or node_modules/react-native-browser/android instead of the folder we just created.

Write some dump function in your NativeModules

After linking our library to Demo project, inside the iOS Project of DemoBrowser, you will see our NativeModule has been attached

iOS Perspective

Look again at the folder tree above, we can see that there are RNBrowser.h and RNBrowser.m inside the ios folder. That is the implementation of iOS Native Module RNBrowser, quick look at the implementation of RNBrowser

RCT_EXPORT_MODULE() : means our Module will have the name as the class name - RNBrowser, or, if you want, you can specific the name you like, but, just make sure that you also change the Module name in the index.js in iOS's part.

Change to another name: RCT_EXPORT_MODULE(NewAwesomeBrowserModule)
in
index.js platform iOS: NewAwesomeBrowserModule.openGoogle();

Now it’s time to write our Module’s method openGoogle in native way.

That’s it, we can try some improvement, but that is pretty enough for opening Google.

Now we back to our demo to see how to use our native module: Open DemoBrowser/App.js then import our Module's method:

import { openGoogle } from 'react-native-browser';

Then we add a Button which is just for Open Google.

Now, it’s time to run the Demo to se how does it work. DemoBrowser> react-native run-ios

It works perfectly as we expected. Nothing much but it’s how we import Native Module to React-Native code. In the next Tutorial, I will explain more about various type of Macros such as RCT_EXPORT_MODULE(), RCT_EXPORT_METHOD(), and how we use them for various purpose, also how we implement the same method on Android. The final step would be publish your awesome library to npm's registry.

Good luck and happy coding!

Originally published at gist.github.com.

--

--