TextInput onContentSizeChange triggers twice inside a Modal
Description
When using a TextInput inside a Modal, the onContentSizeChange callback is triggered twice instead of once. Outside the Modal the event triggers correctly (only once).
Steps to reproduce
- Install and launch the application
- Observe that onContentSizeChange triggers once (as expected)
- Click on the "Show modal" button
- Notice that onContentSizeChange for the TextInput inside the Modal triggers twice (unexpected behavior)
React Native Version
0.76.0
Affected Platforms
Runtime - Android, Runtime - iOS
Output of npx react-native info
System:
OS: Windows 10 10.0.19045
CPU: (8) x64 Intel(R) Core(TM) i5-8350U CPU @ 1.70GHz
Memory: 9.86 GB / 31.84 GB
Binaries:
Node:
version: 20.12.1
path: C:\Program Files\nodejs\node.EXE
Yarn: Not Found
npm:
version: 9.8.1
path: C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK:
Android NDK: 22.1.7171670
Windows SDK: Not Found
IDEs:
Android Studio: AI-231.9392.1.2311.11330709
Visual Studio: Not Found
Languages:
Java: 17.0.8
Ruby: Not Found
npmPackages:
"@react-native-community/cli":
installed: 15.0.0-alpha.2
wanted: 15.0.0-alpha.2
react:
installed: 18.3.1
wanted: 18.3.1
react-native:
installed: 0.76.0
wanted: 0.76.0
react-native-windows: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: Not found
newArchEnabled: Not found
Stacktrace or Logs
(NOBRIDGE) LOG 39.607845306396484
(NOBRIDGE) LOG 20.39215660095215
(NOBRIDGE) LOG 39.607845306396484
Reproducer
https://github.com/ilaloov/textinput-issue
Screenshots and Videos
No response
@ilaloov Is this happening on New architecture as well?
@shubhamguptadream11 Yes, both with new architecture enabled and disabled
| :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 - undefined. 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. |
Hey @ilaloov, do you see this issue happening on both Android and iOS? I can see the issue happening on Android but it seems to be fine on iOS.
@coado I double-checked on iOS (emulator). It might be the emulator, but it triggers twice as well. However, the returned value (height) is constant, whereas on Android, it varies (20.39215660095215, 39.607845306396484).
@ilaloov This is how it works for me on iPhone 16 emulator. The onContentSizeChange in outside TextInput is printed twice initially, but when I open a modal with the inside TextInput it prints only once.
https://github.com/user-attachments/assets/efb75619-a388-4e42-85be-9345f6096625
code
import {Button, Modal, SafeAreaView, StyleSheet, TextInput} from 'react-native';
import React, {useState} from 'react';
export default function App() {
const [modal, setModal] = useState(false);
return (
<SafeAreaView style={styles.container}>
<TextInput
multiline
onContentSizeChange={e => console.log("outside: ", e.nativeEvent.contentSize.height)}
style={styles.textInput}
/>
<Button onPress={() => setModal(true)} title="Show modal" />
<Modal visible={modal}>
<TextInput
multiline
onContentSizeChange={e =>
console.log("inside: ", e.nativeEvent.contentSize.height)
}
style={[styles.textInput, styles.textInputModal]}
/>
<Button onPress={() => setModal(false)} title="Hide modal" />
</Modal>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#ecf0f1',
flex: 1,
justifyContent: 'center',
padding: 8,
},
textInput: {
backgroundColor: 'gray',
},
textInputModal: {
marginTop: 100,
},
});
I think I found what causes this issue. The problem is that on Android the screen size in modal view state is updated asynchronous which leads to triggering onLayout in ReactEditText multiple times. Setting the screen size before the layout happens similarly to how it is handled on iOS seems to fix it. I will try to open a PR shortly.
After updating to the new arch we are having an issue where onContentSizeChange gets called only once. What's weird is even after unmounting and remounting the TextInput it does not get called again.