react-native
react-native copied to clipboard
KeyboardAvoidingView onLayout callback triggers warning "This synthetic event is reused for performance reasons"
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
- Install React Native + React >= v17
- 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>
We encountered the same issue. You can't ignore this warning or filter it out.
Any updates?
+1 - seeing this as well with similar code
I also encountered this, and what I found was:
- On Android, it throws a warning when using
event.persist()
- 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.
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.
Am seeing this too. The workaround I've used is to wrap KeyboardAvoidingView in a plain View and call onLayout on that.
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).
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 thepatches/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.
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.
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.
This issue was closed because it has been stalled for 7 days with no activity.