react-native icon indicating copy to clipboard operation
react-native copied to clipboard

KeyboardAvoidingView onLayout callback triggers warning "This synthetic event is reused for performance reasons"

Open remcoabalain opened this issue 2 years ago • 10 comments

Description

Hi, we're seeing a warning while developing an app with the following contents:

ERROR  Warning: This synthetic event is reused for performance reasons. If you’re seeing this, you’re accessing the property `nativeEvent` on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See https://reactjs.org/link/event-pooling for more information.

It seems to be triggered from this part of code (private repo):

<KeyboardAvoidingView
      onLayout={(event) => {
        if (event && event.nativeEvent && event.nativeEvent?.layout.height < Dimensions.get('screen').height) {
          // When this view is smaller than the screen height it's probably a modal.
          // a modal has some space above the modal which isn't used
          // the modal layout height is most of the time the header + missing space above modal.
          // that's the offset we're missing beneath, so use that as keyboardVerticalOffset
          setModalOffset(Dimensions.get('screen').height - event.nativeEvent?.layout.height);
        }
      }}
>
 // children...
</KeyboardAvoidingView>

However, according to react, event.persist() doesn't do anything anymore and should not be required starting from react v17. We're currently at [email protected], so it seems a bit strange that we see this error. We took a deep dive and noticed that the warning is coming from this repository itself: https://github.com/facebook/react-native/blob/main/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js#L857

We can't seem to fix it and we're now not certain if we do anything wrong or if React Native should not show this warning if you're at React v17 or higher.

If we use onLayout with a View component, the warning doesn't show.

So is this a warning which React Native should not show anymore or are we missing something?

Thanks!

Version

0.70.5

Output of npx react-native info

System: OS: macOS 13.0 CPU: (8) x64 Apple M1 Pro Memory: 18.07 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 16.13.2 - ~/.nvm/versions/node/v16.13.2/bin/node Yarn: 1.22.19 - ~/.nvm/versions/node/v16.13.2/bin/yarn npm: 8.5.1 - ~/.nvm/versions/node/v16.13.2/bin/npm Watchman: Not Found Managers: CocoaPods: 1.11.3 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.1, iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1 Android SDK: API Levels: 30, 31, 32, 33 Build Tools: 29.0.2, 30.0.2, 30.0.3, 31.0.0, 32.0.0, 33.0.0 System Images: android-28 | Google APIs ARM 64 v8a, android-28 | Google APIs Intel x86 Atom_64, android-29 | ARM 64 v8a, android-29 | Google APIs ARM 64 v8a, android-31 | ARM 64 v8a, android-31 | Google APIs ARM 64 v8a, android-32 | Google APIs ARM 64 v8a, android-33 | Google APIs ARM 64 v8a, android-33 | Google APIs Intel x86 Atom_64 Android NDK: Not Found IDEs: Android Studio: 2021.3 AI-213.7172.25.2113.9014738 Xcode: 14.1/14B47b - /usr/bin/xcodebuild Languages: Java: Not Found npmPackages: @react-native-community/cli: Not Found react: 18.2.0 => 18.2.0 react-native: ^0.70.5 => 0.70.5 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

Steps to reproduce

  1. Install React Native + React >= v17
  2. Use KeyboardAvoidingView with onLayout callback and access the event.

Snack, code example, screenshot, or link to a repository

<KeyboardAvoidingView
      onLayout={(event) => {
        if (event && event.nativeEvent && event.nativeEvent?.layout.height < Dimensions.get('screen').height) {
          // When this view is smaller than the screen height it's probably a modal.
          // a modal has some space above the modal which isn't used
          // the modal layout height is most of the time the header + missing space above modal.
          // that's the offset we're missing beneath, so use that as keyboardVerticalOffset
          setModalOffset(Dimensions.get('screen').height - event.nativeEvent?.layout.height);
        }
      }}
>
 // children...
</KeyboardAvoidingView>

remcoabalain avatar Dec 08 '22 15:12 remcoabalain

We encountered the same issue. You can't ignore this warning or filter it out.

KevinvdBurg avatar Dec 12 '22 09:12 KevinvdBurg

Any updates?

KevinvdBurg avatar Feb 01 '23 12:02 KevinvdBurg

+1 - seeing this as well with similar code

crieggalder avatar Feb 04 '23 07:02 crieggalder

I also encountered this, and what I found was:

  1. On Android, it throws a warning when using event.persist()
  2. On iOS, it throws a warning when NOT using event.persist()

..for now I'm calling event.persist?.() with optional chaining to get rid of the warning on iOS.

As @remcoabalain said, it seems like ReactNativeRenderer-dev.js is responsible for this.

pudgereyem avatar Feb 16 '23 09:02 pudgereyem

I just hit this too. KeyboardAvoidingView's onLayout goes async before calling this.props.onLayout, so that's called too late to persist the event. Maybe this.props.onLayout could just be called before the await.

zewt avatar Feb 24 '23 01:02 zewt

Am seeing this too. The workaround I've used is to wrap KeyboardAvoidingView in a plain View and call onLayout on that.

wavesandwaves avatar Aug 16 '23 15:08 wavesandwaves

Yep, exact same problem for me and same use case. Wrapping KeyboardAvoidingView in a plain View seems to cause KeyboardAvoidingView to stop working (for the same hard coded keyboardVerticalOffset value).

tmw102 avatar Oct 05 '23 04:10 tmw102

The workaround found here worked for me, until this is fixed.

The steps I did:

  • Install patch-package: npm install patch-package
  • I edited node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js per the workaround details:
       this._initialFrameHeight = this._frame.height;
     }
 
+    if (this.props.onLayout) {
+      event.persist();
+    }
+
     if (wasFrameNull) {
       await this._updateBottomIfNecessary();
     }
  • Run npx patch-package react-native to create the patches/react-native+0.72.4.patch file (yours will be different, based on the exact version of react-native you use.
  • I edited manually this file before committing, because it was including more than just this change, because of auto-generated source files in that package.

If someone has time, I guess you could open a PR for this in the current repo, and link to this issue. Not sure what could block this from being merged pretty quickly.

gboudreau avatar Nov 08 '23 13:11 gboudreau

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar May 07 '24 05:05 github-actions[bot]

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar May 07 '24 05:05 github-actions[bot]

This issue was closed because it has been stalled for 7 days with no activity.

github-actions[bot] avatar May 14 '24 05:05 github-actions[bot]