software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
9.05k stars 1.31k forks source link

onLayout stops firing after rotation on iPadOS when Animated.View is used #6684

Open mhoran opened 1 week ago

mhoran commented 1 week ago

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 using react-native-reanimated and the New Architecture.

After rotation, the KeyboardAvoidingView eventually stops updating properly. The root cause is that the onLayout 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 to KeyboardAvoidingView. It seems that any React Native project using react-native-reanimated will eventually stop firing onLayout after rotation on iPadOS. 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 extra onLayout being called when an Animated.View is present in the DOM, right before onLayout stops firing. Removing the Animated.View prevents this issue from occurring, and there is only a single onLayout 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

  1. Launch the reproducer on an iPad simulator with npm run ios
  2. Focus the text input at the bottom
  3. Open the on screen keyboard
  4. Rotate screen
  5. Note that onLayout has been printed twice in the log
  6. Rotate the screen again
  7. Note that the KeyboardAvoidingView has applied incorrect padding and that onLayout was not printed in the log

Snack 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

Prior to rotation After rotation
Simulator Screenshot - iPad Air 11-inch (M2) - 2024-11-10 at 11 50 56 Simulator Screenshot - iPad Air 11-inch (M2) - 2024-11-10 at 11 51 03
quentez commented 2 days ago

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