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;
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
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]];
or, you can get it by name:
#import <React/RCTUIManager.h>
RCTUIManager* uiManager = [self.bridge moduleForName:@"RCTUIManager"];
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)
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;
}
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);
Now you can call methods of other modules.
Hope it helps.