react-native-community / discussions-and-proposals

Discussions and proposals related to the main React Native project
https://reactnative.dev
1.66k stars 126 forks source link

TurboModules (NativeModules Re-architecture) #40

Closed fkgozali closed 2 years ago

fkgozali commented 5 years ago

Introduction

This is a place for discussions around the upcoming "TurboModule" feature.

Terminology

TL;DR

From @axe-fb's blogpost, here's a temporary description of TurboModules (please consider that this is not yet finalized, it may change in the future)

The JSI system can also be used to call leverage device capabilities like bluetooth or other sensors by exposing functions that JS can call. This is similar to how browsers expose functions like navigator.geolocation.getCurrentPosition that, when invoked in JavaScript, trigger the respective C++ call in the browser. In the current system, a table with information about module names and methods is created. When JS calls a specific native module, the indices of the module and methods are passed to Java/ObjC, which then invoke the specific methods. The arguments and return values are also converted between JavaScript and JNI/ObjC objects. [...] Now that we have a JSI object for "SampleTurboModule", can invoke methods on this JSI object from JavaScript. During the calls, we also need to convert JSI Values to JNI for argument parameters, and the reverse when sending back results. Like in the current architecture, most types including boolean, strings, Maps, Arrays, Callbacks and Promises are supported.

Available Materials

At ReactConf 2018 @axe-fb did a talk about React Native's New Architecture, which also explains the 3 concepts above: JSI, Fabric, TurboModule.

IN Q1 2019, @kelset wrote a more high-level explanation in a blogpost: https://formidable.com/blog/2019/fabric-turbomodules-part-3/ and did a talk about the whole rearchitecture in April 2019 at React Edinburgh.

@kelset also did a more in-depth talk at React Advanced London in Oct 2019: youtube recording & slides.

Q&A

This is also a place for questions related to this effort and its direction.

fkgozali commented 5 years ago

cc @kelset - wanna label this one with "Transparency"? I don't have access looks like.

cc @axe-fb

empyrical commented 5 years ago

Not sure if native components would get covered by this. But, I wonder, could lazy loading native components take advantage of Suspense? Something like this:

const RCTWebView = lazy(() => lazyRequireNativeComponent('RNCUIWebView'));

Then, in the wrapper component:

<Suspense fallback={this.props.renderPlaceholder()}>
  <RCTWebView />
</Suspense>

The placeholder view could be specified by the developer as a prop.

This may be a little hacky, however, since it expects to be only used with a promise returned from import().

So the promise returned by this hypothetical lazyRequireNativeComponent would need to be an object like: { default: [the native component] }

elicwhite commented 5 years ago

@empyrical, this isn’t related to turbomodules, but rather one of the other projects I’m working on. This won’t need to be lazy because requireNativeComponent won’t exist and the only work that will be done is returning the string “RCTView”. There will be no round trips to native so it won’t provide value to make this async.

tomduncalf commented 5 years ago

Does this proposal (and related parts such as JSI) mean C++ native modules will become a first class, documented citizen of the RN universe?

That would be awesome, I’m doing a lot of work in this area and most of it had to be figured out by reverse engineering/trial and error.

fkgozali commented 5 years ago

Does this proposal (and related parts such as JSI) mean C++ native modules will become a first class, documented citizen of the RN universe?

Depends on what you meant by first class citizen. You can already build C++ class that talks directly to the VM via JSI's HostObject - all JSI code is already in master: https://github.com/facebook/react-native/blob/bf2500e38ec06d2de501c5a3737e396fe43d1fae/ReactCommon/jsi/jsi.h#L80

An example consumer is https://github.com/facebook/react-native/blob/94d49e544d10d0039a1178dc97533e96a4354198/ReactCommon/fabric/uimanager/UIManagerBinding.h

We plan to build a thin C++ wrapper on top of this direct access to HostObject to make the binding slightly easier in the future, but the first focus will be ObjC/Java modules. Documentation will come when they are all ready and stable. So yes, C++ modules will become first class in this angle.

tomduncalf commented 5 years ago

This is really interesting, thanks for the pointers. So far we've been working with CxxModule, looks like this could be a cleaner alternative!

Will have a proper look into it when time allows, we are doing some pretty interesting stuff with C++/React Native integration which pushes it fairly hard and could make a good test case for some of this stuff, so if you'd be interested in discussing in more detail please feel free to get in touch (details in Github bio)!

an-kumar commented 5 years ago

@fkgozali Do you mean in the current version of react native we can already build and register C++ classes using jsi's HostObject to the VM?

Are there any examples of this? I'm particularly unclear on where the registration would occur -- from outside of RN core.

tomduncalf commented 5 years ago

Yeah same question here - would be nice to know the recommended way to register a C++ JSI module

fkgozali commented 5 years ago

Do you mean in the current version of react native we can already build and register C++ classes using jsi's HostObject to the VM?

Yes. We're working on a cleaner abstraction, but at the moment you can try something like this at your own:

would be nice to know the recommended way to register a C++ JSI module

Expect more documentation when TurboModule is ready to use. We moved a bunch of code for iOS already to github, Android coming soon, but sample code will be provided at later time.

tomduncalf commented 5 years ago

Thanks very much - I was looking at this today but it would have taken me a while to figure that out :)

I noticed the Turbomodules stuff in github - seems to be adding a new layer of abstraction for this stuff? Would you say it’s better to develop against what is in master than what is in the RC branch if we want to have more of a chance of keeping close to the final API?

fkgozali commented 5 years ago

I noticed the Turbomodules stuff in github - seems to be adding a new layer of abstraction for this stuff?

That's correct. It's abstraction for crossing C++-->ObjC and C++-->Java. You don't need it if you want to stay in pure C++ via jsi::HostObject.

Would you say it’s better to develop against what is in master than what is in the RC branch if we want to have more of a chance of keeping close to the final API?

Nothing in master/RC is ready to use, but you can get the idea about where we're headed. If you for some reason needs to play with jsi::HostObject sooner, by all means go for it. If you're in no rush, I'd wait for more official guidelines/docs on how to use TurboModule.

tomduncalf commented 5 years ago

@fkgozali I wonder if you'd be able to advise me a little further on the Android side of this? I was able to get it up and running on iOS without too much trouble and it seems great, but on Android I'm having issues and as I'm pretty new to the Android platform, not sure quite where I am going wrong.

You said:

Android Same deal as iOS, but get the runtime off catalystInstance.getJavaScriptContextHolder(), which you can pass down to JNI, then cast it to jsi::Runtime * like in iOS.

So, the only way I could find to get access to the JavaScriptContextHolder was to create a new Native Module, and get hold of this in the initialise method like: long context = getReactApplicationContext().getJavaScriptContextHolder().get(); (in iOS, I was able to do this without a module, in my AppDelegate by just getting .runtime from the RCTCxxBridge instance, but I couldn't work out the equivalent in Android).

I'm then passing the context over JNI to C++, so my native module code looks like:

package com.reactnativejsi;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class JSIModule extends ReactContextBaseJavaModule {
    static {
        System.loadLibrary("test_module_jni");
    }

    public JSIModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public void initialize() {
        super.initialize();

        long context = getReactApplicationContext().getJavaScriptContextHolder().get();
        install(context);
    }

    @Override
    public String getName() {
        return "JSIModule";
    }

    public native void install(long runtime);
}

Then in my TestModule.cpp, I'm installing the module by calling runtime.global().setProperty(runtime, testModuleName, std::move(object)); - the code is roughly:

std::shared_ptr<TestModuleBinding> testModuleBinding;

extern "C" {
  JNIEXPORT void JNICALL
  Java_com_reactnativejsi_JSIModule_install(JNIEnv* env, jobject thiz, jlong runtimePtr) {
    testModuleBinding = std::make_shared<TestModuleBinding>();
    jsi::Runtime* runtime = (jsi::Runtime*) runtimePtr;

    auto testModuleName = "testModule";
    auto object = jsi::Object::createFromHostObject(*runtime, testModuleBinding);
    runtime->global().setProperty(*runtime, testModuleName, std::move(object));
  }
}

But this causes it to crash with a useless stack trace and no errors that I can see in logcat:

image

Indeed, either of the lines auto object = jsi::Object::createFromHostObject(*runtime, testModuleBinding); or runtime->global().setProperty(*runtime, testModuleName, std::move(object)); on their own is enough to cause the crash, or even just trying to access runtime->global() and assign it to something... so I am guessing there is something bad about my runtime instance, but I'm a bit of a loss how to debug further!

Like I say, new to all this so I may be making some stupid mistake – if you have any pointers (heh...) or examples of doing this on Android, I'd be really grateful!

Thanks, Tom

rhysforyou commented 5 years ago

Will TuboModules make it easier to write native modules in Swift? Right now we still have to write Objective-C bridging code which is far from ideal.

rhdeck commented 5 years ago

In case it helps, I wrote a module to automate away the creation of bridging code: NPM: https://www.npmjs.com/package/react-native-swift-bridge GitHub: https://github.com/rhdeck/reactnative-swift-bridge

And eagerly await TM to find out how the bridge changes to similarly make swift code easier for us native devs.

On Thu, Feb 14, 2019 at 8:54 PM Rhys Powell notifications@github.com wrote:

Will TuboModules make it easier to write native modules in Swift? Right now we still have to write Objective-C bridging code which is far from ideal.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/react-native-community/discussions-and-proposals/issues/40#issuecomment-463876452, or mute the thread https://github.com/notifications/unsubscribe-auth/ALov_2APjndVX1WTDOSW5PI8psWUrowHks5vNhNkgaJpZM4XaH5o .

elicwhite commented 5 years ago

@rhdeck that’s awesome and a great idea. We are actually planning on building this into the system for TurboModules. ;-) Have you seen this discussion? https://github.com/react-native-community/discussions-and-proposals/issues/92

fkgozali commented 5 years ago

Will TuboModules make it easier to write native modules in Swift? Right now we still have to write Objective-C bridging code which is far from ideal.

TurboModule foundation is just JSI + platform specific binding. JSI is C++, and for iOS, we need a binding to convert c++ calls into objc++ class methods.

To support swift, such c++ to swift binding needs to be built (we won’t be building this as we’re focused on objc support right now).

Then with codegen, swift code per module can be generated to some degree.

sunnylqm commented 5 years ago

@fkgozali Can you introduce more about the jsi/jsc refactor? Some native modules may need the jsContextRef which is now gone https://github.com/facebook/react-native/commit/c49d3653ef35bb3b932055027af0c0a6bab91d84#diff-e15318f48b6447f2d9936c5e047d882fL395

fkgozali commented 5 years ago

Some native modules may need the jsContextRef which is now gone

See the comment above for now: https://github.com/react-native-community/discussions-and-proposals/issues/40#issuecomment-454138232

Why would you need direct access to the VM though?

sunnylqm commented 5 years ago

@fkgozali the webgl context needs this https://github.com/react-native-community/react-native-webgl/blob/master/cpp/RNWebGL.cpp#L205 I am not familar with c++, is there anyway to access the vm in the legacy native module?

fkgozali commented 5 years ago

I am not familar with c++, is there anyway to access the vm in the legacy native module?

The existing nativemodules system was not designed to provide you access to the VM directly since that can be dangerous (e.g. multithreaded access, since JS is single threaded, etc). The jsContextRef just happened to be added for a different purpose in the past.

With JSI/TurboModule, you can achieve the same thing as https://github.com/react-native-community/react-native-webgl/blob/master/cpp/RNWebGL.cpp#L205 without getting access to the VM. This is done by subclassing JSI HostObject: https://github.com/facebook/react-native/blob/0d7faf6f73b942126e1f45016cde8fd480fd0164/ReactCommon/jsi/jsi.h#L98 -- In fact, TurboModule is just a special subclass of HostObject.

So if your webgl stuff registers itself as TurboModule compatible and you provide your own HostObject subclass, then you don't need any access to the VM directly. This process is work in progress and will be documented when they're ready. For now, you can see the comment above as I previously pasted. https://github.com/react-native-community/discussions-and-proposals/issues/40#issuecomment-454138232

sunnylqm commented 5 years ago

@fkgozali Thanks for your detailed explanation! I'll give it a try.

fkgozali commented 5 years ago

With https://github.com/facebook/react-native/commit/0bd931e47e95544a303bc0aee7a206f8b22ac056, SampleTurboModule was installed into RNTester iOS. You can the sense of how it works end-to-end. To try:

windev92 commented 5 years ago

Hello fkgozali,

I wanted to know the official FB status of

it is officially released? I am looking to 3rd party native components using the new design, and haven't find any that uses the new architecture (host object and fabric). The official facebook documentation still explain how to create a native module with RCT_METHOD(iOS), and @ReactMethod(Java), i.e the old style. I am just wondering if the developments are ready or not, and why the official FB documentation doesn't explain how to create a native module in pure C++ with the new design. It is definitely helpful to have the same code written once for both iOS and android. My other question is about compatibility layer I heard of in some articles, that makes it possible to existing 3rd party modules to work without being recoded. If not official yet, any date for the planned official released? (and the documentation to write new modules, and migrating existing modules to new design of course) Many thanks

fkgozali commented 5 years ago

TurboModule/Fabric are not ready for wide adoption yet, we're still working on it. You can expect announcement & proper documentations when that happens later this year.

jsamr commented 5 years ago

@fkgozali Will those TurboModules provide a uniform interface for promise rejections? As of RN 0.59 rejected error objects shapes vary with platform.

windev92 commented 5 years ago

Hello fkgozali,

thanks for your answer, I have anticipated and implemented my native module with jsi. I have however noticed a problem with Chrome debugger crashing. Now sync function are going to be extensively used by newly created 3rd party native modules, is there any action taken on FB side to allow Chrome debugging with jsi? It is a kinda important feature. many thanks

fkgozali commented 5 years ago

Chrome debugger

Please follow discussions in https://github.com/react-native-community/discussions-and-proposals/issues/7

ducNgbk commented 5 years ago

@sunnylqm Hi, I am trying to make react-native-webgl work with RN0.58 on Android too. Have you managed to make it work on RN 0.58 yet? I'm seeking for any help. Thanks

sav007 commented 5 years ago

Hi folks, I have a question regarding Android. Specifically what all these mean for existing native modules written on Java / Kotlin that lives in JVM world, should they be rewritten on C/C++ in order to be consumed as TurboModules? If not I guess the only way to make them work is using JNI? What about the performance, won't it be a bottleneck JVM -> JNI -> JS as it involves marshalling across the JNI layer? I don't even mention about the complexity it can bring in multithreading environment.

terrysahaidak commented 5 years ago

Hey @sav007, you can use Java/Kotlin as you would use before. Turbomodules aren't about rewriting everything to C++, they are about several things:

  1. Lazy initialization – allows you to initialize module instance only then you calling it at the very first time, not on the app initialization itself.
  2. JSI – JavaScript Interface – in fact, this is the new iteration of the "bridge" helping you triggering all the Java code from the JS. The old bridge has overhead – JSON serialization of each call on both sides – from the JS and from the Java. But JSI allows you to skip that part, so it's much faster.
  3. JSI is completely synchronous.

So you will need to create a module spec and "codegen" the C++ part of it, it will create a JSI "bridge" for your module in order to allow you to call all your methods from JS really easy and get response blazingly fast.

sav007 commented 5 years ago

JSI – JavaScript Interface – in fact, this is the new iteration of the "bridge" helping you triggering all the Java code from the JS. The old bridge has overhead – JSON serialization of each call on both sides – from the JS and from the Java. But JSI allows you to skip that part, so it's much faster.

So in order to build such communication JNI is going to be used, right? That brings to my second question:

What about the performance, won't it be a bottleneck JVM -> JNI -> JS as it involves marshalling across the JNI layer?

https://developer.android.com/training/articles/perf-jni

Minimize marshalling of resources across the JNI layer. Marshalling across the JNI layer has non-trivial costs. Try to design an interface that minimizes the amount of data you need to marshall and the frequency with which you must marshall data.

It looks like the existing RN bridge is going to be replaced by another JNI bridge that concerns me from perf perspective.

terrysahaidak commented 5 years ago

You can be sure that JVM -> JNI -> JS is still waaaaaay faster than a previous serializable bridge. Yes, there is always some overhead, JS VM is already overhead, but it allows us to use all the cool features React provides us.

@axemclion once mentioned on some conference talk that fully Fabric application will allow you to run 60 fps animation using requestAnimationFrame cause the performance of JSI is enough to do it, let's see :)

akshetpandey commented 5 years ago

Is there any guidelines on building C++ JSI turbomodules using cmake? How should I include the header files?

MikkelSnitker commented 5 years ago

Is it possible to expose a "native class" using JSI? Eg. would it be possible to create a native class that can be instantiated using new keyword in JS? (const myinstance = new SomeClass()).

My problem is that the current Blob module does not support \0 characters, and i would like to make a "native" implementation where i can pass the "native" blob instance to my other native code

Forgive my ignorance, but i'm new to JSI.

Mikkel

patrice4github commented 4 years ago

Is there a way to turn off TurboModules for an application? The call to getEnforcing currently returns null in my app and I can't find why to save my life.

It looks like this in TurboModuleRegistry.js:

export function getEnforcing<T: TurboModule>(name: string): T {
  const module = get(name);
  invariant(
    module != null,
    `TurboModuleRegistry.getEnforcing(...): '${name}' could not be found. ` +
      'Verify that a module by this name is registered in the native binary.',
  );
  return module;
}

In order to have my application loading, I hacked around it in the mean time:

export function getEnforcing<T: TurboModule>(name: string): T {
  if (name == "ExceptionsManager") {
    const legacyModule = {
      reportSoftException: () => {},
    }
    return ((legacyModule: any): T);
  } else {
    const legacyModule = NativeModules[name];
    return ((legacyModule: any): T);
  }
}

Anyone would know why the TurboModuleRegistry.getEnforcing is not returning anything?

tomduncalf commented 4 years ago

Hey @patrice4github, AFAIK TurboModules should be off by default unless you call RCTEnableTurboModule(YES); in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions in your AppDelegate.mm.

I actually looked into something similar the other day trying to get TurboModules working. In my case, I was trying to copy how RNTester uses TurboModules, and this error was occurring because my AppDelegate did not implement RCTCxxBridgeDelegate and RCTTurboModuleManagerDelegate correctly.

With current master, it seems you need at a minimum:

#import <React/RCTCxxBridgeDelegate.h>
#import <ReactCommon/RCTTurboModuleManager.h>
#import <React/CoreModulesPlugins.h>

@interface AppDelegate() <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate>{
  RCTTurboModuleManager *_turboModuleManager;
}
# pragma mark - RCTCxxBridgeDelegate

- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
{
  __weak __typeof(self) weakSelf = self;
  return std::make_unique<facebook::react::JSCExecutorFactory>([weakSelf, bridge](facebook::jsi::Runtime &runtime) {
    if (!bridge) {
      return;
    }
    __typeof(self) strongSelf = weakSelf;
    if (strongSelf) {
      strongSelf->_turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge delegate:strongSelf];
      [strongSelf->_turboModuleManager installJSBindingWithRuntime:&runtime];
    }
  });
}

#pragma mark RCTTurboModuleManagerDelegate

- (Class)getModuleClassFromName:(const char *)name
{
  return RCTCoreModulesClassProvider(name);
}

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
jsInvoker:(std::shared_ptr<facebook::react::JSCallInvoker>)jsInvoker
{
  return nullptr;
}

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
instance:(id<RCTTurboModule>)instance
jsInvoker:(std::shared_ptr<facebook::react::JSCallInvoker>)jsInvoker
{
  return nullptr;
}

in your AppDelegate.mm, otherwise there is no getModuleClassFromName implementation and getEnforcing can't look up any modules to instantiate them. This took quite a lot of digging through debug stacks etc. so I suspect this is one part of TurboModules that is not ready for prime – another issue I noticed is that in the latest release, images don't work with TurboModules enabled but they do in master.

patrice4github commented 4 years ago

Thanks for this input, much appreciated.

After my upgrade to 0.61.1, all of my images stopped working, even though I didn't turn TurboModule on. I suspect it could be on by default...

tomduncalf commented 4 years ago

Interesting, I was using 0.61.1 and not seeing that behaviour 🤔 maybe should be reported as a bug against RN if that is happening

Have you tested from a clean react-native init project?

patrice4github commented 4 years ago

react-native init: Yes I have, it's working ok.

I'm toying with the idea of opening a bug. I however don't have a "reproducible scenario" (unless I'm willing to share my entire project, which I'm not at this time. is that just me?). My gut feeling, there's something wrong with PlatformConstants, it gave me some errors yesterday, but that all I have for now. I'm investigating further.

Thanks.

tomduncalf commented 4 years ago

PlatformConstants was the first module I saw the problem with when I enabled Turbomodules, I believe this is just because it is the first native module that the JS tries to call into when it starts up. You can poke around the following bits of RN if you are interested, not got time right now to remember exactly which bits helped diagnose the issue:

image

It sounds like Turbomodules is somehow enabled in your project when it shouldn't be. First I'd check there are no calls to RCTEnableTurboModule(YES); anywhere - you could also drop a breakpoint in the implementation of this, in RCTBridge.m line 106, to check its not being called. You can also verify in line 93 of that file that it defaults to disabled, static BOOL turboModuleEnabled = NO;

patrice4github commented 4 years ago

Thanks for the hint, doing that now. Ah! I was about to say this, my gut feeling is that PlatformConstants is part of the problem...

Screen Shot 2019-10-01 at 10 07 33 AM

It's used quite a bit in react-native-gesture-handler, react-navigation, react-navigation-stack. PlatformConstants in react-native-gesture-handler is problematic I think...

patrice4github commented 4 years ago

static BOOL turboModuleEnabled = NO; at line 93, correct.

RCTEnableTurboModule is not firing.

TurboModuleRegistry.getEnforcing is called nevertheless.

tomduncalf commented 4 years ago

Hmm... I wonder if one of your dependencies is somehow triggering this. Dunno what to suggest except the old "disable dependency and try again" dance ;)

Jonovono commented 4 years ago

@patrice4github any luck?

I'm getting the following error upon upgrading to latest RN version

 *** Terminating app due to uncaught exception 'RCTFatalException: Unhandled JS Exception: Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DevSettings' could not be found. Verify that a module by this name is registered in the native binary.', reason: 'Unhandled JS Exception: Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'DevSettings' could not be found. Verify that a module by this name is registered in the na..., stack:
getEnforcing@2052:28
<unknown>@41002:50
loadModuleImplementation@271:14
<unknown>@40961:40
loadModuleImplementation@271:14
<unknown>@35542:18
loadModuleImplementation@271:14
<unknown>@28660:16
loadModuleImplementation@271:14
guardedLoadModule@163:47
global code@323476:4
'
patrice4github commented 4 years ago

I ended up trashing my project, starting over with a client project, reimporting the files one by one... Took me forever.

I'm realizing that with RN I spend more time investigating and debugging framework issues. Going back to native development for now.

elicwhite commented 4 years ago

@Jonovono do you have TurboModules enabled in your app or are you seeing that getEnforcing error message in a fresh project with TurboModules disabled?

Jonovono commented 4 years ago

@TheSavior it's not a new project, an older project but I just upgraded RN version to 0.61.4 from 0.60.5 and started getting this error. From what I can tell TurboModules isn't enabled.

Weirdly, if I am building the 'debug' configuration it doesn't show up, everything works fine. We have a few custom configurations and it's showing up when I build our Staging configuration.

I came across this: https://github.com/facebook/react-native/issues/26987 and seems like others are having similar issues.

RSNara commented 4 years ago

@Jonovono, in your podspec file, are you depending on the React-CoreModules pod? RCTDevSettings was moved to CoreModules, so you may have to update your dependencies. Please let me know if this fixes your problem.

Jonovono commented 4 years ago

@RSNara hmm, I had pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' in my Podfile already.

RSNara commented 4 years ago

@Jonovono, are other NativeModules in CoreModules also available in the app? You could try to access them via the NativeModules object.