React-Native: Dark art of Native APIs

Whole Native side is open to explore

I’ve been working with React-Native for a long time, it’s not perfect, but it solves the problems that we face — Fast development, cross-platform intermediate performance(CPU usage, memory, etc.) are some of the results of using React-Native.

Every JavaScript developer can use React-Native to build a native application that will run on both platforms iOS & Android.

But at some point, you can feel that JavaScript is not enough to build a full-featured app that you need.

> How can you edit a photo using only JavaScript?

> Can you process video, or detect cars on video using pure JavaScript?

The answer to these questions is No!

React-Native was created by Facebook engineers and allows JavaScript developers to manipulate with application UI, and some APIs using pure JavaScript. Do you know how it’s working?

Single Bridge to connect worlds

React-Native has 3 main parts:

  1. JavaScript Side where React lives.
  2. Bridge — that connects two realms.
  3. Native Side where actually everything is happening.

JavaScript and native sides are very fast! Main performance bottleneck happens when bridge overloads.

When we’re using JavaScript to Vibrate device, we’re using already provided Vibration API It sends commands to native side through Bridge.

When we’re calling

Vibration.vibrate(100);

React-Native sends JSON command to the native side:

{module: 'RCTVibrate', args: [100]}

Then the Native side’s React-Native part handles this command and vibrates the device.

vibrate method

Basically, that’s how everything works. But imagine that we want to have popover in our application and at some point, we see that JavaScript is not a good choice to do this(performance issues, complex JS code, styling mess, etc.).

A popover is a simple thing in native platforms, so why we can’t just use something from the native side and connect it with JavaScript?

Let’s create a native module! (for iOS)

For the first, we need to open our project’s iosfolder with Xcode, then create a new Swift file:

Press next and enter a filename(ex. Popover) then press finish. You’ll see the following window

This is because our project is in Objective-C and we have been creating Swift file which should be connected with ObjC through Bridge(not RN Bridge), so press Create Bridging Header .

Okay, let’s open our Swift file and write some lines there.

So here we created a class named RNPopover which extends from NSObject .

It has only one method show which just prints to the console RNPopover: Show the message, very simple right?

We’ll add directives to make this class and method available for ObjC

Great! Now let’s provide this class & method to JavaScript.

We need to create another file, let’s name it RNPopoverBridge.m and add some lines

We imported React/RCTBridgeModule.h to make it available us to use. Great!

Now let’s export our Swift code to JavaScript

Okay, no need to deeply understand what here is going on, now we need to export show method

Now in JavaScript you can find it with this signature.NativeModules.RNPopover.show()

Okay, so now we need to pass arguments from JavaScript to Swift, for that we’ll do the following

We’ll add normal argument on Swift side, and then we’ll need to change method signature for the bridge to keep it connected with the JavaScript world.

Here we go.

We added show: (NSString *) it says that show method should accept one string argument.

Now after calling our show method from JavaScript and passing some string on it, you can find RNPopover: Show YOUR_STRING_HERE log in Xcode logs.

Now let’s search popover library for Swift in GitHub, I found this awesome library https://github.com/corin8823/Popover.

Now let’s create a new swift file in our project and copy all code from

https://github.com/corin8823/Popover/Classes/Popover.swift into our file.

Okay, now we need to use it in our Popover.swift file

And here’s where everything is happening.

We used UIKit to have access for native UI components like UIView, UILabel.

We’re using DispatchQueue.main.async which allows us to run code inside UI thread which is an only one thread from where we allowed drawing UI.

And after compiling and running you can see that popover is shown!

Well done, now we also can use the string that we passed from JavaScript

Used title as a text for popover label

Aaah, All this may seem to you strange — why it’s hard to make the connection between two worlds. It’s not hard if you know two worlds, creating a connection is hard if you’re not familiar with Native side.

And here you go! We created a native module to draw Popover on the screen.

API for Android will be pretty simple, simpler than for iOS(because here we used Swift if you know Objective-C — then for you iOS will be simpler).

So we see how two worlds have been connected through Bridge.

--

--

Shahen Hovhannisyan
Research & Engineering at Simply Technologies

JS hacker, Deep Learning enthusiast, Sportsman, Founder at Actoservice. Software Architect