One of the biggest reason for the popularity of React Native is that we can create a bridge between the Native language and JavaScript code. Which means we can reuse all the reusable libraries created in iOS and Android world. To create a production grade application some point of time you need to use Native Bridge. There are very less article and tutorial on cross-platform React Native bridge which works on both iOS and Android. In this article, we will create a Native Bridge to access Swift and Java class from JavaScript. This is the first part, second post on can be found . Native Bridge of UI component here The code of this article can be found here -> https://github.com/nalwayaabhishek/LightApp Create the LightApp To better understand Native Module we will create a simple LightApp example using react-native CLI. $ react-native init LightApp$ cd LightApp Next, we will create a class in Swift for iOS and Java for Android, and this will be used this app in a React component. Bulb This will be cross-platform example and the same React code will work in both iOS and Android. As we have created a basic skeleton of the project, next we have divided this article into two sections: Section 1 — Native Bridge in iOS Section 2 — Native Bridge in Android Section 1 —Native Bridge iOS In this section, we will focus on iOS and create a bridge between Swift/Objective C and your React Component. It has these three steps: Step 1) Create a Bulb class and Bridge Header Step 2) Understanding GCD Queue and fixing the warning: Step 3) Accessing a variable in JavaScript from Swift and Callbacks Step 1) Create a Bulb class and Bridge Header To get started we will create a Bulb class in swift, which will have a static class variable and a few other functions. And then we will access this swift class from Javascript. Let's start by opening file in ios folder. It should open Xcode with your ios code. isOn LightApp.xcodeproj Once you open the project in Xcode, then create a new Swift file Bulb.swift as shown: We have also clicked on Create Bridging Header which will create a file This will help to communicate between Swift and Objective C code. Remember that in a project we have only one Bridge Header file. So if we add new files, we can reuse this file. LightApp-Bridging-Header.h Update following code in file: LightApp-Bridging-Header.h #import "React/RCTBridgeModule.h" RCTBridgeModule will provide an interface to register a bridge module. Next update with the following code: Bulb.swift Foundation import @objc(Bulb) Bulb: NSObject { class @objc isOn = **false static var ** @objc turnOn() { func Bulb.isOn = true print("Bulb is now ON") } } We have created class which is inherited from . The root class of most Objective-C class hierarchies is , from which subclasses inherit a basic interface to the runtime system and the ability to behave as Objective-C objects. We can see that we have used @objc before a function and class, this will make that class, function or object available to Objective C Bulb NSObject NSObject The @objc attribute makes your Swift API available in Objective-C and the Objective-C runtime. Now create a new file from and select Objective-C file and then name the file as and update following code: File -> New -> File Bulb.m #import "React/RCTBridgeModule.h" RCT_EXTERN_MODULE(Bulb, NSObject) @interface RCT_EXTERN_METHOD(turnOn) @end React Native will not expose any function of Bulb to React JavaScript unless explicitly done. To do so we have used macro. So we have exposed Bulb class and function to our Javascript code. Since Swift object is converted to Javascript object, there is a type of conversation. RCT_EXPORT_METHOD supports all standard JSON object types: RCT_EXPORT_METHOD() turnOn NSString to string NSInteger, float, double, CGFloat, NSNumber to number BOOL to boolean NSArray to array NSDictionary to object with string keys and values of any type from this list RCTResponseSenderBlock to function Now let’s update JavaScript code and access this class from our React component. To do so open and update with the following code: Bulb App.js import React, {Component} from 'react'; import {StyleSheet, Text, View, NativeModules, Button} from 'react-native'; export default class App extends Component{ turnOn = () => { NativeModules.Bulb.turnOn(); } render() { return ( <View style={styles.container}> <Text style={styles.welcome}>Welcome to Light App!!</Text> <Button onPress={this.turnOn} title="Turn ON " color="#FF6347" /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, }); Now run the iOS simulator: Now open Xcode console to see the logs and we can see that Swift method is called from JavaScript code. (As we have done logging in the method) turnOn Step 2) Understanding GCD Queue and fixing the warning: Now let's fix the warning shown at the bottom of the simulator and in browser console: Module Bulb requires main queue setup since it overrides `init` but doesn’t implement `requiresMainQueueSetup`. In a future release React Native will default to initializing all native modules on a background thread unless explicitly opted-out of. To understand it better let's understand about all the thread React Native runs: : where UIKit work Main thread where the layout happens Shadow queue: where your JS code is actually running JavaScript thread: Every native module has its own GCD Queue unless it specifies otherwise. Now since this Native module will run on a different thread and our main thread is depended on it, it's showing this warning. And to make this code to run on MainQueue, open Bulb.swift and add this function. @objc static func requiresMainQueueSetup() -> Bool { return true } You can explicitly mention to run this in separate threat. return false Step 3) Accessing a variable in JavaScript from Swift and Callbacks Now let's add the Bulb Status(ON or OFF) value to our React screen. To do so we will add function to and call that method from JavaScript code. We will create this method as a callback. getStatus Bulb.swift React Native bridge is asynchronous, so the only way to pass a result to JavaScript is by using callbacks or emitting events Let's update the code in bold in Bulb.swift @objc(Bulb) class Bulb: NSObject { @objc static var isOn = false @objc func turnOn() { Bulb.isOn = true print("Bulb is now ON") } @objc func turnOff() { Bulb.isOn = false print("Bulb is now OFF") } @objc func getStatus(_ callback: RCTResponseSenderBlock) { callback([NSNull(), Bulb.isOn]) } @objc static func requiresMainQueueSetup() -> Bool { return true } } method receives a callback parameter that we will pass from your JavaScript code. And we have called the callback with array of values, which will be exposed in JavaScript. We have passed NSNull() as the first element, which we have considered as an error in the callback. getStatus() We need to expose this Swift method to JavaScript so following bold lines to : Bulb.m @interface RCT_EXTERN_MODULE(Bulb, NSObject) RCT_EXTERN_METHOD(turnOn) RCT_EXTERN_METHOD(turnOff) RCT_EXTERN_METHOD(getStatus: (RCTResponseSenderBlock)callback) @end We have exposed (RCTResponseSenderBlock) as params to the function callback getStatus And then finally update the React Code: import React, {Component} from 'react'; import {StyleSheet, Text, View, NativeModules, Button} from 'react-native'; export default class App extends Component{ constructor(props) { super(props); this.state = { isOn: false }; this.updateStatus(); } turnOn = () => { NativeModules.Bulb.turnOn(); this.updateStatus() } turnOff = () => { NativeModules.Bulb.turnOff(); this.updateStatus() } updateStatus = () => { NativeModules.Bulb.getStatus( (error, isOn)=>{ this.setState({ isOn: isOn}); }) } render() { return ( <View style={styles.container}> <Text style={styles.welcome}>Welcome to Light App!!</Text> <Text> Bulb is {this.state.isOn ? "ON": "OFF"}</Text> {!this.state.isOn ? <Button onPress={this.turnOn} title="Turn ON " color="#FF6347" /> : <Button onPress={this.turnOff} title="Turn OFF " color="#FF6347" /> } </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, }); Rebuild the code and run the app, you can see the Bulb Status value and when you click on then it will show Turn ON Bulb is ON Do remember to rebuild the code instead of refresh, as we changed Native Code. Section 2 — Native Bridge in Android In this section, we will make the same Javascript code which we return for iOS to work with Android. This time we will create class in Java and expose the same function ant to Javascript. Bulb turnOn, TurnOff getStatus Open Android Studio and click on project and then select the folder inside our LightApp. Once all gradle dependency is downloaded, create a Java Class Bulb.java as shown: Open an existing Android Studio android And update the following code in Bulb.java: com.lightapp; com.facebook.react.bridge.NativeModule; com.facebook.react.bridge.ReactApplicationContext; com.facebook.react.bridge.ReactContext; com.facebook.react.bridge.ReactContextBaseJavaModule; com.facebook.react.bridge.ReactMethod; com.facebook.react.bridge.Callback; package import import import import import import Bulb ReactContextBaseJavaModule { Boolean = ; Bulb(ReactApplicationContext reactContext) { (reactContext);} public class extends private static isOn false public super @ReactMethod **public void** getStatus( Callback successCallback) { successCallback.invoke(**null**, _isOn_); } @ReactMethod **public void** turnOn() { _isOn_ \= **true**; System.**_out_**.println(**"Bulb is turn ON"**); } @ReactMethod **public void** turnOff() { _isOn_ \= **false**; System.**_out_**.println(**"Bulb is turn OFF"**); } @Override **public** String getName() { **return "Bulb"**; } } We have created a Java class which is inherited from . requires that a function called is always implemented. The purpose of this method is to return the string name of the NativeModule which represents this class in JavaScript. So here we will call this so that we can access it through in JavaScript. Instead of Bulb, we can have a different name also. Bulb ReactContextBaseJavaModule ReactContextBaseJavaModule getName Bulb React.NativeModules.Bulb Not all function is exposed to Javascript explicitly, to expose a function to JavaScript a Java method must be annotated using The return type of bridge methods is always void. @ReactMethod. We have also created a function which has params as callback and it returns a and passes the value of static variable . getStatus callback isOn Next step is to register the module, if a module is not registered it will not be available from JavaScript. Create a file by clicking on Menu File -> New -> Java Class and the file name as and then click OK. And then add following code to BulbPackage BulbPackage.java com.lightapp; com.facebook.react.ReactPackage; com.facebook.react.bridge.NativeModule; com.facebook.react.bridge.ReactApplicationContext; com.facebook.react.uimanager.ViewManager; package import import import import java.util.ArrayList; java.util.Collections; java.util.List; import import import BulbPackage ReactPackage {@Override List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { Collections. ();} public class implements public return emptyList @Override **public** List<NativeModule> createNativeModules( ReactApplicationContext reactContext) { List<NativeModule> modules = **new** ArrayList<>(); modules.add(**new** Bulb(reactContext)); **return** modules; } } We need to Override function and add the Bulb object to modules array. If this is not added here then it will not be available in JavaScript. createNativeModules package needs to be provided in the method of the file. This file exists under the android folder in your react-native application directory. Update the following code in BulbPackage getPackages MainApplication.java android/app/src/main/java/com/LightApp /MainApplication.java public class MainApplication extends Application implements ReactApplication {... @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>_asList_( new MainReactPackage(), ** new BulbPackage()** ); } ....} We don’t need to change any JavaScript code written in iOS, as we have exposed the same class name and function. If you have skipped the iOS part then you need to copy the React Javascript code from App.js Now run the App through Android Studio or from : react-native run-android Woo!! we can see the Bulb status on the screen and can switch ON or OFF from the button. The great thing is that we have created a Native Bridge which is Cross Platform. What's Next? In this article, we have exposed a class method from Swift/Java to JavaScript. In the next article, we have focused on exposing Swift/Java code as UI components.