Repository navigation
Uncontrolled multiline TextInput doesn't auto-grow #54570
Copy link
Copy link
Open
Labels
Component: TextInputRelated to the TextInput component.Related to the TextInput component.Issue: Author Provided ReproThis issue can be reproduced in Snack or an attached project.This issue can be reproduced in Snack or an attached project.Needs: React Native Team Attention
Description
Description
Uncontrolled multiline TextInput doesn't grow in size when its content spans multiple lines while typing.
Minimum reproducible code:
<View
style={{ height: 500, justifyContent: "center", padding: 20, width: 180 }}
>
<TextInput
multiline
placeholder="height increases"
defaultValue="super long text that will cause the height to span multiple lines"
enablesReturnKeyAutomatically={true}
returnKeyType="go"
style={{
borderWidth: 1,
fontSize: 13,
padding: 4,
// multilineExpandable
height: "auto",
maxHeight: 100,
}}
/>
</View>ScreenRecording_11-17-2025.21-53-10_1.mov
If the defaultValue is long enough to take multiple lines, then it does auto-grow/shrink on subsequent edits
ScreenRecording_11-17-2025.22-00-48_1.MP4
Steps to reproduce
- paste the reproduction code snippet to an empty screen
- try typing into the input until the content starts wrapping
React Native Version
0.81.4
Affected Platforms
Runtime - iOS
Output of npx @react-native-community/cli info
System:
OS: macOS 26.1
CPU: (10) arm64 Apple M4
Memory: 1.16 GB / 32.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 24.8.0
path: ~/.nvm/versions/node/v24.8.0/bin/node
Yarn:
version: 4.9.2
path: ~/.n/bin/yarn
npm:
version: 11.6.0
path: ~/.nvm/versions/node/v24.8.0/bin/npm
Watchman: Not Found
Managers:
CocoaPods:
version: 1.16.2
path: /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 25.1
- iOS 26.1
- macOS 26.1
- tvOS 26.1
- visionOS 26.1
- watchOS 26.1
Android SDK: Not Found
IDEs:
Android Studio: Not Found
Xcode:
version: 26.1.1/17B100
path: /usr/bin/xcodebuild
Languages:
Java:
version: javac 25
path: ~/.sdkman/candidates/java/current/bin/javac
Ruby:
version: 2.6.10
path: /usr/bin/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 19.1.0
wanted: "*"
react-native:
installed: 0.81.4
wanted: "*"
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: Not found
newArchEnabled: Not found
iOS:
hermesEnabled: Not found
newArchEnabled: Not found
Stacktrace or Logs
-
MANDATORY Reproducer
https://snack.expo.dev/@vova.sqds/uncontrolled-multiline-textinput-doesnt-auto-grow
Screenshots and Videos
No response
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Component: TextInputRelated to the TextInput component.Related to the TextInput component.Issue: Author Provided ReproThis issue can be reproduced in Snack or an attached project.This issue can be reproduced in Snack or an attached project.Needs: React Native Team Attention
Activity
valentinchelle commentedon Nov 22, 2025
Following.
Thotaharshavardhani commentedon Nov 24, 2025
I was able to reproduce this issue, this issue happens only on iOS with the New Architecture (Fabric). The TextInput auto-expands correctly for the initial multi-line defaultValue, but after clearing and typing again it stops resizing. Works fine on Android and on iOS Legacy Architecture.
Nedi11 commentedon Nov 25, 2025
+1, is there any workaround in the meantime, besides making it controlled
vova-sqds commentedon Nov 27, 2025
haven't found any :|
sintylapse commentedon Jan 23, 2026
The workaround is to set defaultValue as multiline initially and then set text to the true default value on render
tmw102 commentedon Jan 24, 2026
It's very hacky but I've had success creating a hidden View absolutely positioned exactly under the TextInput with a Text element inside it set to the value and style of the TextInput.
Using the View's
onLayoutChange()I take the height of the View and animate the TextInput to that height.@sintylapse I couldn't get your solution working in my code.
Fix uncontrolled multiline TextInput not resizing when children change
Fix uncontrolled multiline TextInput not resizing when children change
Fix uncontrolled multiline TextInput not resizing when children change
victoriomolina commentedon May 1, 2026
+1
iqorlobanov commentedon May 14, 2026
+1
feat(mobile): TextField + AutosizeTextArea primitives
feat(mobile): Multica for iOS — first version (#2337)
feat(mobile): Multica for iOS — first version (multica-ai#2337)
TheBlueFriend commentedon Aug 31, 2026
I primarily use React Native to build websites. There is the same issue on web. Works fine on Android.
Fix chat composer: grow to 6 lines and shrink back after send
Fix uncontrolled multiline TextInput not resizing when children change
cadumillet commentedon Oct 25, 2026
We hit this too and traced the cause on iOS / Fabric. It reproduces in a blank
npx @react-native-community/cli init --version 0.86.3app (New Architecture on, prebuilt core, Xcode 27.1, iOS 26.5 simulator), and the same code is unchanged in 0.88.0 and onmain.Minimal repro: an uncontrolled
<TextInput multiline placeholder="Title" style={{ fontSize: 22, lineHeight: 28, padding: 8 }} />that mounts empty. Type a sentence longer than one line: the field stays one line high, the text scrolls and the first line is cut off. The same field withdefaultValue="a"grows as expected.Root cause (
ReactCommon/react/renderer/components/textinput/BaseTextInputShadowNode.h, line numbers as of 0.86.3):updateStateIfNeeded(L154) returns early when the React-tree attributed string is content-equal to the state'sreactTreeAttributedString(L160). For a field that mounts empty, both have zero fragments, soisContentEqualistrueand the state is never written. The state keeps its defaultreactTreeAttributedString, whose baseTextAttributes::fontSizeMultiplieris NaN (TextAttributes.hL49,quiet_NaN()).RCTTextInputComponentView_updateStateupdates onlyattributedStringBox.reactTreeAttributedStringkeeps the NaN multiplier.attributedStringBoxToMeasure(L199) setsmeaningfulState(L201) only if the state'sreactTreeAttributedString.getBaseTextAttributes().fontSizeMultiplier == layoutContext.fontSizeMultiplier. NaN never compares equal, someaningfulStateis alwaysfalse.meaningfulStatefalse, the node measuresgetAttributedString(layoutContext)fromprops.text. For an uncontrolled input that stays empty, so it falls back togetPlaceholderAttributedString(L217) and measures the placeholder: one line.A field that mounts with text gets past step 1 (the strings differ), so its state gets a real multiplier and
meaningfulStatebecomes true after the first native update. That matches the reports above: a longdefaultValueworks, and an empty start does not.A possible fix: write the state when the base text attributes differ even if the content is equal, or treat a NaN multiplier in the state as "not set" so it does not block
meaningfulState.@janicduplessis, #56291 looks related (stale
attributedStringBoxwhen children change). From the description I couldn't tell whether it also covers this NaN-multiplier path for a plain uncontrolled input that mounts empty. It may be worth a check.Workaround we use: an invisible
Textwith the field's exact font, line height, padding and font scaling, holding the current text (fromonChangeText, or the placeholder when empty). TheTextInputis laid absolutely over it, so the copy sizes the container. The copy is hidden from accessibility (aria-hidden,importantForAccessibility="no-hide-descendants") and haspointerEvents="none". Making the input controlled also avoids it, but brings back the stale-eventCountwrite-back problem while typing.