Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write react native "native module" ( bridge ) that reuses common JavaScript code?

How can a native module callback to a JavaScript internal bridge method, then do processing in the internal method, for example parsing data into JSON, and then raise an event that the react native app receives?

For cross-platform bridge modules, I want to avoid duplicating code in both Objective C and Java. When possible, I want to write cross-platform bridge module code in JavaScript and reuse for Android and iOS.

My Current Solution:

This works.

This will result in two calls to sendEventWithName:

  1. sendEventWithName with the "_processResponseInJavaScriptMethod"
  2. forwardEventWithName to sendEventWithName to the react native app.

Question:

Is there an approach for native code to process data synchronously using a JS call, then send results immediately with sendEventWithName?

Or does every native > JS call require an async _bridge enqueueJSCall?

File: MyNativeModule.m

// Use forwardEventWithName to forward events 
// processed by common cross-platform JS to the react native app
RCT_EXPORT_METHOD(forwardEventWithName:(NSString*)name
                  body:(NSString*)body) {
    [self sendEventWithName:name body:body];
}

// 1 - react native app calls sendQueryToBluetoothDevice
// 2 - device calls commandResponse when response received
RCT_EXPORT_METHOD(sendQueryToBluetoothDevice:(NSString*)command {
    [_device sendCommand:command];
}

// 1 - Receives XML response from external Bluetooth device
// 2 - Sends XML to internal JS method for processing
// 3 - Internal JS method uses forwardEventWithName 
//     to send event to react native app
- (void) commandResponse:(NSString *) xml {    
    [self sendEventWithName:@"_processResponseInJavaScriptMethod"
                       body:@{@"xml": configuration}];

}

File: index.js ( native module )

 // Parse xml in common JS code for both Android and iOS native modules
emitter.addListener("_processResponseInJavaScriptMethod", (e) => {
    const body = parseXml(e.xml);

    // ?? Is there a way to send event directly using JS to the react native app ??

    // Hack - Call native method forwardEventWithName to sendEventWithName to react native app.
    ///
    // This makes two _bridge enqueueJSCall's
    // 1 - One call to sendEventWithName "_myNativeModuleInternalMethod"
    // 2 - Second call to sendEventWithName "myNativeModuleEvent
    MyNativeModule.forwardEventWithName(
      'myNativeModuleEventResponseReceived', 
       JSON.stringify(body));
  }
})
like image 852
Ed of the Mountain Avatar asked May 31 '17 17:05

Ed of the Mountain


People also ask

Is React Native bridge synchronous?

The Bridge This way of messaging is fundamentally asynchronous. The bridge also exposes an interface for Java/ObjC to schedule JavaScript execution, typically used for callbacks from Native Modules.

What is RCT in React Native?

A native module is an Objective-C class that implements the RCTBridgeModule protocol. If you are wondering, RCT is an abbreviation of ReaCT.

What is a bridge and why is it used in React Native explain for both Android and iOS?

React Native is developed in such a way that we can create a bridge between the Native Language and the JavaScript code. A bridge is nothing but a way to setup communication between native platform and React Native.


Video Answer


1 Answers

I would recommend doing some reading on the Batched Bridge in React Native.

Native -> JS

Essentially what you can do is define a module with static methods on the JS side which you would then register with the BatchedBridge (registerCallableModule) - this then enables you to directly call this method from the native side via RCTBridge().enqueueJSCall, where you would provide the moduleDotMethod that corresponds to your module and function respectively; you would also pass a unique (or incremental) identifier that you would later use to map the response to each request.

JS -> Native

Next you would create a Native Module that would be called on the JS side to send data back to native, passing the response data and identifier which you would then handle on the native side.

I've worked on projects where the entire service layer is on the JS side and have used this approach successfully.

like image 192
sooper Avatar answered Sep 21 '22 05:09

sooper