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:
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)); } })
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.
A native module is an Objective-C class that implements the RCTBridgeModule protocol. If you are wondering, RCT is an abbreviation of ReaCT.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With