javascript react react-native react-native-bridge Technology ui-component

React Native Bridge for Android and iOS — UI Component

Go to the profile of Abhishek Nalwaya

That is Half 2 of React Native Bridge tutorial, Half 1 targeted on bridging Native courses to React. The tutorial may be founder right here.

On this tutorial, we’ll give attention to creating cross-platform React Native element which can work in each Android and iOS.

In Half 1 of React Native Bridge, I began with iOS and then defined Android. This time I’ll begin with Android and then clarify ios. (Simply to be pure 😉). However in the long run, the identical React UI element will work on iOS and Android.

The code of this text may be discovered right here -> https://github.com/nalwayaabhishek/LightViewApp

Create the LightApp

To raised perceive Native Module we’ll create a easy LightViewApp instance utilizing react-native CLI.

$ react-native init LightViewApp
$ cd LightApp

Subsequent, we’ll create a element in Swift for iOS and Java for Android, and this shall be used this app in a React element. This might be cross-platform instance and the identical React code will work in each iOS and Android.

As we have now created a primary skeleton of the undertaking, subsequent we have now divided this text into two sections:

Part 1 — Native Bridge UI element in Android

Part 2 — Native Bridge UI element in iOS

Part 1 — Native Bridge UI element in Android

On this part, we’ll concentrate on Android and create a bridge between Swift/Goal C and your React Component. It has these three steps:

Step 1) Create Bulb UI element

Step 2) Passing props to element

Step three) Passing the Native state to React element

Step 1) Create a Bulb View element

To get began we’ll create a BulbView class in swift which can inherit from Android Button class. After which use this in our react code as element <Bulb />.

Open Android Studio and click on on Open an present Android Studio challenge and then choose the android folder inside our LightViewApp. As soon as all gradle dependency is downloaded, create a Java Class BulbView.java as proven:

As soon as the file is created, replace the next code in BulbView.java:

package deal com.lightviewapp;

import android.content material.Context;
import android.graphics.Shade;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;

import com.fb.react.bridge.Arguments;
import com.fb.react.bridge.ReactContext;

public class BulbView extends Button

public BulbView(Context context)
tremendous(context);
this.setTextColor(Colour.BLUE);
this.setText(“This button is created from JAVA code”);

public BulbView(Context context, AttributeSet attrs)
tremendous(context, attrs);

public BulbView(Context context, AttributeSet attrs, int defStyle)
tremendous(context, attrs, defStyle);

We now have created a BulbView java class which is inherited from Button, and overwrite the constructor. We will customise Button shade and button textual content.

Subsequent, we’ll create a BulbManager to show and replace the next code in BulbManager.java:

package deal com.lightviewapp;

import com.fb.react.uimanager.SimpleViewManager;
import com.fb.react.uimanager.ThemedReactContext;

public class BulbManager extends SimpleViewManager<BulbView>

@Override
public String getName()
return “Bulb”;

@Override
protected BulbView createViewInstance(ThemedReactContext reactContext)

return new BulbView(reactContext);

We now have inherited BulbManager class from SimpleViewManager . A SimpleViewManager is a React Native interface accountable for instantiating and updating views within the app. The SimpleViewManager is a generic class that makes use of our view.

We all the time want a Customized Supervisor class which ought to be inherited from SimpleViewManager or its dad or mum class ViewManager

And in each Supervisor class, there ought to be all the time these two issues:

  • A way identify getName, which return string identify, which shall be uncovered to JavaScript
  • Implement createViewInstance(ThemedReactContext reactContext)technique through which we create an occasion of the element and return the item.

Supervisor class can be additionally used within the subsequent part, the place we’ll move props from React Component.

Subsequent step is to register the module, if a module just isn’t registered it won’t be obtainable from JavaScript. Create a file by clicking on Menu File -> New -> Java Class and the file identify as BulbPackage and then click on OK. After which add the next code to BulbPackage.java

package deal com.lightviewapp;
import com.fb.react.ReactPackage;
import com.fb.react.bridge.NativeModule;
import com.fb.react.bridge.ReactApplicationContext;
import com.fb.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Listing;
public class BulbPackage implements ReactPackage
@Override
public Listing<NativeModule> createNativeModules(ReactApplicationContext reactContext)
return Collections.emptyList();

@Override
public Record<ViewManager> createViewManagers(ReactApplicationContext reactContext)
return Collections.<ViewManager>singletonList(
new BulbManager()
);

We have to Override createNativeModules perform and add the Bulb object to modules array. If this isn’t added right here then it won’t be obtainable in JavaScript.

BulbPackage package deal must be offered within the getPackages technique of the MainApplication.java file. This file exists beneath the android folder in your react-native software listing. Replace the next code in android/app/src/foremost/java/com/LightViewApp /MainApplication.java

public class MainApplication extends Software implements ReactApplication

@Override
protected Record<ReactPackage> getPackages()
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new BulbPackage()
);

….

Now let’s replace JavaScript code and entry <Bulb> element from our React element. To take action open App.js and replace with the next code:

import React, Component from ‘react’;
import StyleSheet, Textual content, View, requireNativeComponent from ‘react-native’;const Bulb = requireNativeComponent(“Bulb”)export default class App extends Component render() return ( <View type=types.container> <View type=types.prime /> <Bulb fashion= types.backside /> </View>);
const types = StyleSheet.create(container: flex: 1,backgroundColor: ‘#F5FCFF’,,prime: flex: 1,alignItems: “center”,justifyContent: “center”,,backside: flex: 1,alignItems: “center”,justifyContent: “center”,,);

Now run the react native app:

Woo 💥 we will see <Bulb> has rendered a UI button which we now have created in Java. The dimensions and place of the button is set from stylesheet which we have now outlined in React element.

Step 2) Passing props to element

On this part, we’ll prolong Bulb element to simply accept props. We’ll add a props isOn to Bulb UI element, which can change the colour of the button, we created within the final part.

<Bulb fashion= types.backside isOn=true/>

First let’s deal with our button for accepting clicks utilizing OnClickListener. OnClickListener registers a callback to be invoked once we do some operation on Button and onClick might be referred to as when clicked a button. On clicking of button, we modify the worth of isOn. Which then will change the colour and textual content of the button.

Open BulbView and replace the next code:

package deal com.lightviewapp;

import android.content material.Context;
import android.graphics.Colour;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;

import com.fb.react.bridge.Arguments;
import com.fb.react.bridge.ReactContext;
import com.fb.react.bridge.WritableMap;
import com.fb.react.uimanager.occasions.RCTEventEmitter;

public class BulbView extends Button
public Boolean isOn = false;
public void setIsOn (Boolean initialBulbStatus)
isOn = initialBulbStatus;
updateButton();

public BulbView(Context context)
tremendous(context);
this.setTextColor(Colour.BLUE);
this.setOnClickListener(changeStatusListener);
updateButton();

public BulbView(Context context, AttributeSet attrs)
tremendous(context, attrs);

public BulbView(Context context, AttributeSet attrs, int defStyle)
tremendous(context, attrs, defStyle);

personal OnClickListener changeStatusListener = new OnClickListener()
public void onClick(View v)
isOn = !isOn;
updateButton();

;

personal void updateButton()
if (isOn)
setBackgroundColor(Colour.YELLOW);
setText(“Switch OFF”);
else
setBackgroundColor(Shade.BLACK);
setText(“Switch ON”);

Subsequent we’ll settle for isOn prop from JavaScript and assign the worth of isOn to our class Bulb. Open BulbManager.java and add the next code:

public class BulbManager extends SimpleViewManager<BulbView> ….@ReactProp(identify=”isOn”)
public void setBulbStatus(BulbView bulbView, Boolean isOn)
bulbView.setIsOn(isOn);
….

After which replace the react code in App.js:

<Bulb type= types.backside isOn=true/>

Now run the app in Android simulator:

We will see the state of Bulb is handed to Android. You possibly can attempt to change the worth of isOn=false and attempt to refresh the display.

Passing the Native state to React element

Now let’s add the Bulb Standing(ON or OFF) worth to our React display. To take action we’ll add _onStatusChange perform to Bulb element and it will name when the button standing is change. We’ll cross the perform in element like this:

<Bulb fashion= types.backside isOn=this.state.isOn onStatusChange=this._onStatusChange />

Lets get began and replace BulbView.js

package deal com.lightviewapp;
…import com.fb.react.bridge.Arguments;
import com.fb.react.bridge.ReactContext;
import com.fb.react.bridge.WritableMap;
import com.fb.react.uimanager.occasions.RCTEventEmitter;

public class BulbView extends Button
….
personal void changeStatus()
WritableMap occasion = Arguments.createMap();
occasion.putBoolean(“isOn”, isOn);
ReactContext reactContext = (ReactContext)getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
getId(),
“statusChange”,
occasion);

if (isOn)
setBackgroundColor(Colour.YELLOW);
setText(“Switch OFF”);
else
setBackgroundColor(Shade.BLACK);
setText(“Switch ON”);

When a local occasion happens the native code challenge an occasion to the JavaScript illustration of the View, and the 2 views are linked with the worth returned from the getId() technique.

To map the statusChange occasion identify to the onStatusChange callback prop in JavaScript, register it by overriding the getExportedCustomBubblingEventTypeConstants technique in your ViewManager. So lets replace BulbManager.java

….

import com.fb.react.widespread.MapBuilder;
import java.util.Map;

public class BulbManager extends SimpleViewManager<BulbView>

@Override
public Map getExportedCustomBubblingEventTypeConstants()
return MapBuilder.builder()
.put(
“statusChange”,
MapBuilder.of(
“phasedRegistrationNames”,
MapBuilder.of(“bubbled”, “onStatusChange”)))
.construct();

Lastly let’s create _onStatusChange perform in JavaScript, which might be referred to as as soon as the button is clicked. Replace the React code in App.js:

import React, Component from ‘react’;import StyleSheet, Textual content, View, requireNativeComponent from ‘react-native’;const Bulb = requireNativeComponent(“Bulb”)export default class App extends Component constructor(props) tremendous(props); this._onStatusChange = this._onStatusChange.bind(this); this.state = isOn: false ;_onStatusChange = e => this.setState( isOn: e.nativeEvent.isOn);render() return (<View type=types.container><View fashion=types.prime > <Textual content>This state of Bulb come from Native Code to JavaScript</Textual content> <Textual content>this.state.isOn ? “Bulb is On” : “Bulb is Off”</Textual content></View><Bulb type= types.backside isOn=this.state.isOn onStatusChange=this._onStatusChange /></View>);const types = StyleSheet.create(container: flex: 1,backgroundColor: ‘#F5FCFF’,,prime: flex: 1,alignItems: “center”,justifyContent: “center”,,backside: flex: 1,alignItems: “center”,justifyContent: “center”,,);

Now run the app in Android Simulator

Woo we will see that within the prime part the state of Bulb is mirrored.

Part 2 — Native Bridge UI element in iOS

On this part, we’ll make the identical Javascript code which we used for Android to work with iOS. This time we’ll create Bulb View class in Swift and expose the identical implementation in Javascript.

To get began we’ll create a BulbView class in swift, which may have a category variable isOn and a number of different features. After which we’ll entry this swift class from Javascript as a element. Let’s begin by opening LightViewApp.xcodeproj file in ios folder. It ought to open Xcode together with your ios code.

When you open the venture in Xcode, then create a brand new Swift file BulbView.swift as proven:

We’ve additionally clicked on Create Bridging Header which can create a file LightViewApp-Bridging-Header.h This can assist to speak between Swift and Goal C code. Keep in mind that in a challenge we’ve just one Bridge Header file. So if we add new information, we will reuse this file.

Replace following code in LightViewApp-Bridging-Header.hfile:

#import “React/RCTBridgeModule.h”#import “React/RCTViewManager.h”#import “React/RCTEventEmitter.h”

RCTBridgeModule will present an interface to register a bridge module.

Subsequent, we’ll replace BulbView.swiftwith the next code:

import UIKitclass BulbView: UIView @objc var onStatusChange: RCTDirectEventBlock?@objc var isOn: Bool = false didSet button.setTitle(String(describing: isOn ? “Switch Off” : “Switch On”), for: .regular)button.backgroundColor = isOn ? .yellow : .blackoverride init(body: CGRect) tremendous.init(body: body)self.addSubview(button)required init?(coder aDecoder: NSCoder) fatalError(“init has not been implemented”)lazy var button: UIButton = let button = UIButton.init(sort: UIButton.ButtonType.system)button.titleLabel?.font = UIFont.systemFont(ofSize: 20)button.autoresizingMask = [.flexibleWidth, .flexibleHeight]button.addTarget(self,motion: #selector(changeBulbStatus),for: .touchUpInside)return button()@objc func changeBulbStatus() isOn = !isOn as BoolonStatusChange!([“isOn”: isOn])

We’ve got created a Bulb View which is inherited from UIButton. We’ve additionally created a variable isOn which outline the colour and textual content of the button. Clicking on the button will name changeBulbStatus technique.

Now create Bulb.swift as Swift file:

And replace the next code

import Basis@objc(Bulb)class Bulb: RCTViewManager override func view() -> UIView! return BulbView()

We’ve created Bulb class which is inherited from RCTViewManager. The basis class of most View class in React Native hierarchies is RCTViewManager, from which subclasses inherit a primary interface to the runtime system and the power to behave as Goal-C objects. We will see that we have now used @objc earlier than a perform and class, this can make that class, perform or object obtainable to Goal C

The @objc attribute makes your Swift API obtainable in Goal-C and the Goal-C runtime.

Now create a brand new file from File -> New -> File and choose Goal-C file and then identify the file as Bulb.m and replace following code:

#import “React/RCTViewManager.h”@interface RCT_EXTERN_MODULE(Bulb, RCTViewManager)RCT_EXPORT_VIEW_PROPERTY(isOn, BOOL)RCT_EXPORT_VIEW_PROPERTY(onStatusChange, RCTDirectEventBlock)@finish

React Native won’t expose any perform of Bulb to React JavaScript until explicitly completed. To take action we have now used RCT_EXPORT_METHOD() macro. So we now have uncovered Bulb class and property to our Javascript code. Since Swift object is transformed to Javascript object, there’s a sort of dialog. RCT_EXPORT_METHOD helps all normal JSON object varieties:

  • NSString to string
  • NSInteger, float, double, CGFloat, NSNumber to quantity
  • BOOL to boolean
  • NSArray to array
  • NSDictionary to object with string keys and values of any sort from this listing
  • RCTResponseSenderBlock to perform

Essential Observe: If in case you have skipped the Android a part of this publish, then it is advisable copy the React code in App.js.

Now run the appliance in iOS Simulator:

Now let’s repair the warning proven on the backside of the simulator and in browser console:

Module Bulb requires major queue setup because it overrides `init` however doesn’t implement `requiresMainQueueSetup`. In a future launch React Native will default to initializing all native modules on a background thread until explicitly opted-out of.

To know it higher let’s perceive about all of the thread React Native runs:

  • Principal thread: the place UIKit work
  • Shadow queue: the place the format occurs
  • JavaScript thread: the place your JS code is definitely operating

Each native module has its personal GCD Queue until it specifies in any other case. Now since this Native module will run on a special thread and our principal thread is trusted it, it’s displaying this warning. And to make this code to run on MainQueue, open Bulb.swift and add this perform.

@objcstatic func requiresMainQueueSetup() -> Bool return true

You possibly can explicitly point out return false to run this in separate menace.

Woo!! We have now created a Native Bridge UI which is Cross Platform. If you wish to examine Native Bridge out right here. Hope you discover this handy. Please share your ideas in feedback. When you appreciated the publish, please share and give few claps👏