Inter-communication between native modules on React Native

Takuya Matsuyama - Feb 19 '21 - - Dev Community

React Native apps can be extended by native modules.
While they are easy to use from JavaScript, doing so between native modules is not officially documented.
I have several own native modules and I wanted to call those methods from another native module in ObjC/Swift/Java/Kotlin, so that I can avoid writing duplicate code.
I've dug into the core of React Native to understand how to do that.

iOS

Understanding RCTBridge

RCTBridge is the class to communicate with the JavaScript app.
It provides several useful methods to work with other native modules:

/**
 * Retrieve a bridge module instance by name or class. Note that modules are
 * lazily instantiated, so calling these methods for the first time with a given
 * module name/class may cause the class to be synchronously instantiated,
 * potentially blocking both the calling thread and main thread for a short time.
 *
 * Note: This method does NOT lazily load the particular module if it's not yet loaded.
 */
- (id)moduleForName:(NSString *)moduleName;
- (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad;
// Note: This method lazily load the module as necessary.
- (id)moduleForClass:(Class)moduleClass;
Enter fullscreen mode Exit fullscreen mode

You can get an instance of a module with these methods.

Get an RCTBridge instance

In your bridge module, you have to add a property for RCTBridge like so:

@interface YourModule : NSObject <RCTBridgeModule>

@property (nonatomic, weak) RCTBridge *bridge;

@end

@implementation YourModule

@synthesize bridge = _bridge;

@end
Enter fullscreen mode Exit fullscreen mode

That's it.
The bridge property is automatically set when your module is initialized.

Get another native module instance

For example, you can get an instance of RCTUIManager like so:

#import <React/RCTUIManager.h>

RCTUIManager* uiManager = [self.bridge moduleForClass:[RCTUIManager class]];
Enter fullscreen mode Exit fullscreen mode

or, you can get it by name:

#import <React/RCTUIManager.h>

RCTUIManager* uiManager = [self.bridge moduleForName:@"RCTUIManager"];
Enter fullscreen mode Exit fullscreen mode

Android

Understanding ReactContext

ReactContext class is similar to RCTBridge in iOS.
It provides a handy method to work with other native modules like so:

  /** @return the instance of the specified module interface associated with this ReactContext. */
  public <T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface)
Enter fullscreen mode Exit fullscreen mode

It allows you to get an instance of a native module by class.

Get an instance of ReactContext

In your bridge module, your code should already look like:

public class YourModule extends ReactContextBaseJavaModule {
    private final ReactApplicationContext reactContext;

    public AttachmentProcessorModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }
Enter fullscreen mode Exit fullscreen mode

So, you can quickly access via this.reactContext.

Get another native module instance

For example, you can get an instance of UIManagerModule like so:

import com.facebook.react.uimanager.UIManagerModule;

UIManagerModule uiManagerModule = this.reactContext.getNativeModule(UIManagerModule.class);
Enter fullscreen mode Exit fullscreen mode

Now you can call methods of other modules.
Hope it helps.


Subscribe Newsletter

My YouTube channel

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .