Synchronous returns in React Native native modules

Alec Larson
2 min readAug 21, 2018

--

Have a native module for React Native whose API would be nicer if its methods’ return values weren’t promises?

Yes, it’s possible. The following examples show a function that takes a string converted from Javascript world and returns it synchronously. No promises necessary!

iOS version

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(
echoString:(NSString *)input
) {
return input;
}

Android version

@ReactMethod(isBlockingSynchronousMethod = true)
public String echoString(String input) {
return input;
}

More details are found in the ReactAndroid source code:

Whether the method can be called from JS synchronously on the JS thread, possibly returning a result.

WARNING: in the vast majority of cases, you should leave this to false which allows your native module methods to be called asynchronously: calling methods synchronously can have strong performance penalties and introduce threading-related bugs to your native modules.

In order to support remote debugging, both the method args and return type must be serializable to JSON: this means that we only support the same args as ReactMethod, and the hook can only be void or return JSON values (e.g. bool, number, String, WritableMap, or WritableArray).

Calling these methods when running under the websocket executor is currently not supported.

A slightly different message can be found in the iOS source code:

Same as RCT_EXPORT_METHOD but the method is called from JS synchronously on the JS thread, possibly returning a result.

WARNING: in the vast majority of cases, you should use RCT_EXPORT_METHOD which allows your native module methods to be called asynchronously: calling methods synchronously can have strong performance penalties and introduce threading-related bugs to your native modules.

The return type must be of object type (id) and should be serializable to JSON. This means that the hook can only return nil or JSON values (e.g. NSNumber, NSString, NSArray, NSDictionary).

Calling these methods when running under the websocket executor is currently not supported.

The general recommendation is to avoid synchronous returns, so be careful out there!

--

--