-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
onLayout stops firing after rotation on iOS when Animated.View is used #6684
Comments
This does not seem limited to iPadOS as I'm seeing similar issues on iOS using KeyboardAvoidingView. Reproduction here: https://github.com/quentez/keyboard-bug-repro |
I've tracked the issue down to the following line of code: Line 617 in b2b58a6
When the layout event is dispatched from React Native, it is intercepted by react-native-reanimated. I traced the event from the However, the I traced the event through react-native-reanimated is picked up by the event listener: react-native-reanimated/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm Lines 145 to 154 in b2b58a6
I see that the event listener receives the Interestingly, other events such as |
I've confirmed that the I've further simplified the repro on the In the broken state, I see two attempts to dispatch layout events by Returning prior to line 617 in |
Okay, I figured it out. First, why does this only happen with I noticed that, while react-native-reanimated was receiving the onLayout event as expected, a second event was being dispatched from React Native, but then dropped before reaching JavaScript. This is because of the above guard, ultimately setting the dispatched value to When Line 617 in b2b58a6
the lambda defined in the BaseViewEventEmitter is evaluated (see https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.cpp#L16). react-native-reanimated receives the layout value, but since the layoutEventState->wasDispatched flips to true , when React Native receives the event it is ignored.
It seems that the I'm not sure how best to address this issue. It looks like this change was introduced in fe587cf by @piaskowyk, @tomekzaw and @michalmaka; perhaps they can weigh in. |
Previously, NativeReanimatedModule::handleRawEvent would intercept all events received by the event listener. This resulted in an issue where onLayout would not fire in JS on the New Architecture. Instead, only intercept events with waiting handlers. This prevents asJSIValue from being called on the Reanimated event loop and allows onLayout to bubble up in JS. See https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewEventEmitter.cpp#L82-L112, which prevents onLayout from being dispatched more than once. asJSIValue evaluates the lambda above in https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.cpp#L16. Fixes software-mansion#6684
I've opened a PR that resolves this issue and would appreciate feedback. |
@mhoran Thanks for opening the PR, we'll review it shortly |
Previously, NativeReanimatedModule::handleRawEvent would intercept all events received by the event listener. This resulted in an issue where onLayout would not fire in JS on the New Architecture. Instead, only intercept events with waiting handlers. This prevents asJSIValue from being called on the Reanimated event loop and allows onLayout to bubble up in JS. See https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewEventEmitter.cpp#L82-L112, which prevents onLayout from being dispatched more than once. asJSIValue evaluates the lambda above in https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.cpp#L16. Fixes software-mansion#6684
Previously, NativeReanimatedModule::handleRawEvent would intercept all events received by the event listener. This resulted in an issue where onLayout would not fire in JS on the New Architecture. Instead, only intercept events with waiting handlers. This prevents asJSIValue from being called on the Reanimated event loop and allows onLayout to bubble up in JS. See https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewEventEmitter.cpp#L82-L112, which prevents onLayout from being dispatched more than once. asJSIValue evaluates the lambda above in https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.cpp#L16. Fixes software-mansion#6684
Previously, NativeReanimatedModule::handleRawEvent would intercept all events received by the event listener. This resulted in an issue where onLayout would not fire in JS on the New Architecture. Instead, only intercept events with waiting handlers. This prevents asJSIValue from being called on the Reanimated event loop and allows onLayout to bubble up in JS. See https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewEventEmitter.cpp#L82-L112, which prevents onLayout from being dispatched more than once. asJSIValue evaluates the lambda above in https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.cpp#L16. Fixes software-mansion#6684
Any update on this? This issue causes KeyboardAvoidingView not animating for Expo SDK 52 projects |
The lack of animation is likely due to #6751. This issue causes the keyboard avoiding view to stop avoiding the keyboard when the device is rotated, or some other layout event changes the size of the frame (e.g. window resized using Stage Manager, etc.) |
Previously, NativeReanimatedModule::handleRawEvent would intercept all events received by the event listener. This resulted in an issue where onLayout would not fire in JS on the New Architecture. Instead, only intercept events with waiting handlers. This prevents asJSIValue from being called on the Reanimated event loop and allows onLayout to bubble up in JS. See https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewEventEmitter.cpp#L82-L112, which prevents onLayout from being dispatched more than once. asJSIValue evaluates the lambda above in https://github.com/facebook/react-native/blob/v0.76.2/packages/react-native/ReactCommon/react/renderer/core/ValueFactoryEventPayload.cpp#L16. Fixes software-mansion#6684
Description
Since upgrading to React Native 0.76 (via Expo 52) I've been trying to track down an issue with
KeyboardAvoidingView
on iPadOS. Despite the resolution of a related bug in React Native, the issue persisted in a project usingreact-native-reanimated
and the New Architecture.After rotation, the
KeyboardAvoidingView
eventually stops updating properly. The root cause is that theonLayout
handler stops being called. This causes_relativeKeyboardHeight
to calculate the wrong height due to a stale frame height. As such, the height is set to 0 and no padding is applied.The
onLayout
bug is not limited toKeyboardAvoidingView
. It seems that any React Native project using react-native-reanimated will eventually stop firingonLayout
after rotation oniPadOSiOS. This issue is limited to the New Architecture. If I switch to the old architecture, the issue does not reproduce.The provided repro shows this behavior. When running in a simulator or device, rotating the screen will show the keyboard either pushing up the main content with too much padding (simulator) or hiding the input text box completely (real device). The
console.log
also shows an extraonLayout
being called when anAnimated.View
is present in the DOM, right beforeonLayout
stops firing. Removing theAnimated.View
prevents this issue from occurring, and there is only a singleonLayout
call during rotation.I thought this issue may have been Expo specific. However, after further testing and isolation of the reproducer, I found that it can be reproduced using React Native without Expo as well. I also isolated the issue to react-native-reanimated, initially believing it was due to an interaction with react-native-gesture-handler.
Steps to reproduce
npm run ios
onLayout
has been printed twice in the logKeyboardAvoidingView
has applied incorrect padding and thatonLayout
was not printed in the logSnack or a link to a repository
https://github.com/mhoran/keyboard-avoiding-view-repro/
Reanimated version
3.16.1
React Native version
0.76.1
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native
Architecture
Fabric (New Architecture)
Build type
Debug app & dev bundle
Device
iOS simulator
Device model
iPad Air 11-inch (M2)
Acknowledgements
Yes
Screenshots
The text was updated successfully, but these errors were encountered: