Closed gregbrinker closed 1 year ago
:warning: | Newer Version of React Native is Available! |
---|---|
:information_source: | You are on a supported minor version, but it looks like there's a newer patch available - 0.70.14. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases. |
@gregbrinker I think it's because sensors lib has retain cycle, can you try this PR? https://github.com/react-native-sensors/react-native-sensors/pull/458
@zhongwuzw giving that a try!
@zhongwuzw that worked! Amazing - thanks so much. Looks like this isn't a React Native issue, but rather an issue with that library in particular
The Issue
Hello! The last few months, my team has noticed that sometimes when the app is reloaded, it crashes. It didn't affect anything in production, so we just let it be. However we finally got annoyed enough with it that we decided to start looking into it. It turns out that in our case, it's due to the
RNSensorsGravity
module fromreact-native-sensors
Here's the error that's logged in Xcode:
This error is from the
RCTAssert
inRCTEventEmitter
:Investigation
I searched around and found many issues related to this, but none were helpful:
So I started digging more into the native code. Immediately before the code that sends the event over the bridge, I added log:
Here's what it logged out. The last log before the crash shows that
self.callableJSModules = nil
, which triggers theRCTAssert
to crash:I was curious, so I wrapped the
[self sendEventWithName ...]
in a check to ensure thatself._callableJSModules
isn't nil:Something interesting happens here. After I reload the app, here's what is logged:
And then if I reload a 3rd time...
It appears that the
RCTEventEmitter
forRNSGravity
are being created, but never cleaned up. In our code, we have auseEffect
that subscribes to the event, and on unmount removes the subscription:The
unsubscribe()
never gets called, but the Native Module continues attempting to send events over the bridge. Every time the app is reloaded, a freshRCTEventEmitter
is created, which works fine - but the old ones are stale and would trigger crashes had I not wrapped thesendEventWithName
code in the check forself._callableJSModules
.Solution?
I'm not quite sure how to accomplish it, but I believe I need to find a way to "destroy"
RCTEventEmitters
when the bridge is reloaded. I attempted to add listeners toRCTEventEmitter
to callinvalidate
whenever the bridge is reloaded, but that didn't work:I mentioned earlier that this is only a problem in DEV, because the prod app rarely restarts. The one time that it does that I can think of is during a CodePush, where
[super.bridge reload]
is called.I'm hoping that someone knows of a way to accomplish this. I imagine that this is an issue for any library that relies on subscriptions.
Thanks!
React Native Version
0.70.8
Output of
npx react-native info
System: OS: macOS 13.0 CPU: (8) arm64 Apple M1 Pro Memory: 72.22 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 18.12.0 - ~/.volta/tools/image/node/18.12.0/bin/node Yarn: Not Found npm: 8.19.2 - ~/.volta/tools/image/node/18.12.0/bin/npm Watchman: 2023.02.20.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.12.0 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.4, iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4 Android SDK: API Levels: 29, 30, 31, 32, 33 Build Tools: 30.0.2, 30.0.3, 31.0.0, 32.0.0, 33.0.2 System Images: android-29 | Intel x86 Atom_64, android-29 | Google APIs ARM 64 v8a, android-32 | Google APIs ARM 64 v8a, android-33 | Google APIs ARM 64 v8a Android NDK: Not Found IDEs: Android Studio: 2022.1 AI-221.6008.13.2211.9619390 Xcode: 14.3/14E222b - /usr/bin/xcodebuild Languages: Java: 11.0.13 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 18.1.0 => 18.1.0 react-native: 0.70.8 => 0.70.8 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found
Steps to reproduce
RCTEventEmitter
(In my case,react-native-sensors
- but any subscription would do)R
in terminal, or "Reload" in the Dev MenuSnack, screenshot, or link to a repository
It technically doesn't run online because it isn't a real device, but here's what the code would look like
https://snack.expo.dev/I6s2wglbh