React Native JSI: How to call any javascript function from native?

1.3k views Asked by At

I need to have a callback function to listen for some events in native module and transfers data from native to javascript and I want to call this javascript function from native directly in React Native iOS app without sending events to NativeEventEmitter.

How to implement this with JSI (JavaScript Interface)?

1

There are 1 answers

1
iUrii On BEST ANSWER

First, your function must be defined globally in javascript e.g.:

App.js

global.greeting = function(param) {
    return "Hello " + param + "!";
};

Then you should find and call it with React Native Runtime in native:

AppDelegate.mm

#include <jsi/jsi.h>
#import <React/RCTBridge+Private.h>

using namespace facebook::jsi;
using namespace std;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  ...
  
  // Runtime notification
  [NSNotificationCenter.defaultCenter addObserverForName:RCTJavaScriptDidLoadNotification object:nil queue:nil
                                              usingBlock:^(NSNotification* notification) {
    // Get runtime
    RCTCxxBridge* cxxbridge = (RCTCxxBridge*)notification.userInfo[@"bridge"];
    if (cxxbridge.runtime) {
      Runtime& runtime = *(Runtime*)cxxbridge.runtime;
      
      // Get global function
      Function greeting = runtime.global().getPropertyAsFunction(runtime, "greeting");
      
      // Call with param
      Value param = Value(runtime, String::createFromUtf8(runtime, "JSI"));
      Value result = greeting.call(runtime, move(param), 1);
      
      string str = result.asString(runtime).utf8(runtime);
      printf("Result: %s", str.c_str());
    }
  }];
  return YES;
}

Outputs:

Result: Hello JSI!

Note: Since the sample uses JSI for synchronous native methods access, remote debugging (e.g. with Chrome) is no longer possible. Instead, you should use Flipper for debugging your JS code.