Using Native SDKs and Libraries in React Native

Emilio Rodriguez

April 07th, 2016

When building an app in React Native we may end up needing to use third-party SDKs or libraries. Most of the time, these are only available in their native version, and, therefore, only accessible as Objective-C or Swift libraries in the case of iOS apps or as Java Classes for Android apps. Only in a few cases these libraries are written in JavaScript and even then, they may need pieces of functionality not available in React Native such as DOM access or Node.js specific functionality. In my experience, this is one of the main reasons driving developers and IT decision makers in general to run away from React Native when considering a mobile development framework for their production apps.

From the 7th to the 13th November save up to 80% on some of our very best ReactJS content. EBooks, video courses - we've got you covered when it comes to cutting edge web development. Find all our featured titles here as we celebrate Angular and React all week.

The creators of React Native were fully aware of this potential pitfall and left a door open in the framework to make sure integrating third-party software was not only possible but also quick, powerful, and doable by any non-iOS/Android native developer (i.e. most of the React Native developers).

As a JavaScript developer, having to write Objective-C or Java code may not be very appealing in the beginning, but once you realize the whole process of integrating a native SDK can take as little as eight lines of code split in two files (one header file and one implementation file), the fear quickly fades away and the feeling of being able to perform even the most complex task in a mobile app starts to take over. Suddenly, the whole power of iOS and Android can be at any React developer’s disposal.

To better illustrate how to integrate a third-party SDK we will use one of the easiest to integrate payment providers: Paymill. If we take a look at their site, we notice that only iOS and Android SDKs are available for mobile payments. That should leave out every app written in React Native if it wasn’t for the ability of this framework to communicate with native modules. For the sake of convenience I will focus this article on the iOS module.

Step 1: Create two native files for our bridge.

We need to create an Objective-C class, which will serve as a bridge between our React code and Paymill’s native SDK. Normally, an Objective-C class is made out of two files, a .m and a .h, holding the module implementation and the header for this module respectively.

To create the .h file we can right-click on our project’s main folder in XCode > New File > Header file. In our case, I will call this file PaymillBridge.h.

For React Native to communicate with our bridge, we need to make it implement the RTCBridgeModule included in React Native. To do so, we only have to make sure our .h file looks like this:

// PaymillBridge.h
#import "RCTBridgeModule.h"
@interface PaymillBridge : NSObject <RCTBridgeModule>
@end

We can follow a similar process to create the .m file: Right-click our project’s main folder in XCode > New File > Objective-C file.

The module implementation file should include the RCT_EXPORT_MODULE macro (also provided in any React Native project):

// PaymillBridge.m
@implementation PaymillBridge
RCT_EXPORT_MODULE();
@end

A macro is just a predefined piece of functionality that can be imported just by calling it. This will make sure React is aware of this module and would make it available for importing in your app.

Now we need to expose the method we need in order to use Paymill’s services from our JavaScript code. For this example we will be using Paymill’s method to generate a token representing a credit card based on a public key and some credit card details: generateTokenWithPublicKey. To do so, we need to use another macro provided by React Native: RCT_EXPORT_METHOD.

// PaymillBridge.m
@implementation PaymillBridge
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(generateTokenWithPublicKey: 
(NSString *)publicKey  
cardDetails:(NSDictionary *)cardDetails callback:(RCTResponseSenderBlock)callback) {
	//… Implement the call as described in the SDK’s documentation …
	callback(@[[NSNull null], token]);
}
@end

In this step we will have to write some Objective-C but most likely it would be a very simple piece of code using the examples stated in the SDK’s documentation.

One interesting point is how to send data from the native SDK to our React code. To do so you need to pass a callback as you can see I did as the last parameter of our exported method. Callbacks in React Native’s bridges have to be defined as RCTResponseSenderBlock. Once we do this, we can call this callback passing an array of parameters, which will be sent as parameters for our JavaScript function in React Native (in our case we decided to pass two parameters back: an error set to null following the error handling conventions of node.js, and the token generated by Paymill natively).

Step 2: Call our bridge from our React Native code.

Once the module is properly set up, React Native makes it available in our app just by importing it from our JavaScript code:

// PaymentComponent.js
var Paymill = require('react-native').NativeModules.PaymillBridge;
Paymill.generateTokenWithPublicKey(
'56s4ad6a5s4sd5a6', 
cardDetails, 
function(error, token){
console.log(token);
});

NativeModules holds the list of modules we created implementing the RCTBridgeModule. React Native makes them available by the name we chose for our Objective-C class name (PaymillBridge in our example). Then, we can call any exported native method as a normal JavaScript method from our React Native Component or library.

Going Even Further

That should do it for any basic SDK, but React Native gives developers a lot more control on how to communicate with native modules. For example, we may want to force the module to be run in the main thread. For that we just need to add an extra method to our native module implementation:

// PaymillBridge.m
@implementation PaymillBridge 
//...
- (dispatch_queue_t)methodQueue
{
  return dispatch_get_main_queue();
}

Just by adding this method to our PaymillBridge.m React Native will force all the functionality related to this module to be run on the main thread, which will be needed when running main-thread-only iOS API.

And there is more: promises, exporting constants, sending events to JavaScript, etc. More complex functionality can be found in the official documentation of React Native; the topics covered on this article, however, should solve 80 percent of the cases when implementing most of the third-party SDKs.

About the Author

Emilio Rodriguez started working as a software engineer for Sun Microsystems in 2006. Since then, he has focused his efforts on building a number of mobile apps with React Native while contributing to the React Native project. These contributions helped his understand how deep and powerful this framework is.

comments powered by Disqus