I am trying to create a TurboModule
for android
with ReactNative v0.69
Following are the steps which I followed for creating TurboModules
I enabled Hermes
and newArchEnabled
project.ext.react = [ enableHermes: true]
In gradle.properties
newArchEnabled=true
I created a js
folder in root of the project and create NativeCalculator.js
// @flowimport type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport';import {TurboModuleRegistry} from 'react-native';export interface Spec extends TurboModule { // your module methods go here, for example: add(a: number, b: number): Promise<number>;}export default (TurboModuleRegistry.get<Spec>('Calculator'): ?Spec);
In app/build.gradle
apply plugin: "com.facebook.react"react { reactRoot = rootProject.file("../node_modules/react-native/") codegenDir = rootProject.file("../node_modules/react-native-codegen/") jsRootDir = rootProject.file("../js/") libraryName = "calculator" codegenJavaPackageName = "com.firstapp.codegen"}
In java/com/firstapp/newarchitecture/modules
Created CalculatorModule.java
, file
public class CalculatorModule extends NativeCalculatorSpec { public static final String NAME = "Calculator"; public CalculatorModule(ReactApplicationContext context) { super(context); } @Override public String getName() { return NAME; } @ReactMethod public void add(double a, double b, Promise promise) { Log.i("here123","Values are"+a+" "+b); promise.resolve(a + b); }}
In MainApplication.java
In getPackages
method added following code
packages.add(new TurboReactPackage() { @Nullable @Override public NativeModule getModule(String name, ReactApplicationContext reactContext) { if (name.equals(CalculatorModule.NAME)) { return new CalculatorModule(reactContext); } else { return null; } } @Override public ReactModuleInfoProvider getReactModuleInfoProvider() { return () -> { final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>(); moduleInfos.put( CalculatorModule.NAME, new ReactModuleInfo( CalculatorModule.NAME, CalculatorModule.NAME, false, // canOverrideExistingModule false, // needsEagerInit true, // hasConstants false, // isCxxModule true // isTurboModule ) ); return moduleInfos; }; }});@NonNull@Overrideprotected ReactPackageTurboModuleManagerDelegate.Builder getReactPackageTurboModuleManagerDelegateBuilder() { return new MainApplicationTurboModuleManagerDelegate.Builder();}@Nullable@Overrideprotected JSIModulePackage getJSIModulePackage() { return new JSIModulePackage() { @Override public List<JSIModuleSpec> getJSIModules( final ReactApplicationContext reactApplicationContext, final JavaScriptContextHolder jsContext) { final List<JSIModuleSpec> specs = new ArrayList<>(); specs.add(new JSIModuleSpec() { @Override public JSIModuleType getJSIModuleType() { return JSIModuleType.UIManager; } @Override public JSIModuleProvider<UIManager> getJSIModuleProvider() { final ComponentFactory componentFactory = new ComponentFactory(); CoreComponentsRegistry.register(componentFactory); final ReactInstanceManager reactInstanceManager = getReactInstanceManager(); ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry( reactInstanceManager.getOrCreateViewManagers( reactApplicationContext)); return new FabricJSIModuleProvider( reactApplicationContext, componentFactory, new EmptyReactNativeConfig(), viewManagerRegistry); } }); return specs; } };}
In main/jni/Android.mk
include $(GENERATED_SRC_DIR)/codegen/jni/Android.mkLOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jniLOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jniLOCAL_SHARED_LIBRARIES := \.....libreact_codegen_calculator \.....
In MainApplicationModuleProvider.cpp
#include <calculator.h>std::shared_ptr<TurboModule> MainApplicationModuleProvider( const std::string moduleName, const JavaTurboModule::InitParams ¶ms) { // Here you can provide your own module provider for TurboModules coming from // either your application or from external libraries. The approach to follow // is similar to the following (for a library called `samplelibrary`: // auto module = calculator_ModuleProvider(moduleName, params); if (module != nullptr) { return module; } // return rncore_ModuleProvider(moduleName, params); return rncore_ModuleProvider(moduleName, params);}
In App.js
import NativeCalculator from './js/NativeCalculator';
on Button press I have following code
const onPress = async () => { console.log(NativeCalculator); const theAnswer = await NativeCalculator?.add(4, 5); Alert.alert('Answer', 'The answer is '+ theAnswer); };
I tried console logging NativeCalculator
but I get null
The entire source code is available here https://github.com/PritishSawant/reactnativeandroidturbomoduleV2