Skip to content

Commit e0159c1

Browse files
Preserve TextInput returnKeyType when changing multiline (#58355)
Summary: `RCTCopyBackedTextInput` is called when a `TextInput` switches between single-line and multiline and the Fabric component view swaps its backing UIKit view (`RCTUITextField` <-> `RCTUITextView`). It copies the keyboard traits across to the replacement view, but `returnKeyType` is not among them — `keyboardType` is copied on the line directly above it. Because the prop itself has not changed across the transition, the prop diff in `RCTTextInputComponentView` sees `done` -> `done` and does not re-run the setter. The replacement view therefore keeps its default Return key, so an input declared `returnKeyType="done"` renders the newline key instead of Done once it has flipped to multiline. This is the same class of omission that was fixed for `tintColor` in #57748, and the fix is the same shape: copy the property along with its neighbours. Repro: a `TextInput` with a stable key and `returnKeyType="done"` whose `multiline` prop goes `false` -> `true`. After the transition, focusing it shows the default Return key. Fabric view recycling can produce the same backing-view transition even for an input that is always multiline, which makes it intermittent in real apps. Verified against 0.86.3; the line is still missing on 0.87.1 and on `main`. ## Changelog: [IOS] [FIXED] - Preserve TextInput returnKeyType when switching between single-line and multiline backing views. Pull Request resolved: #58355 Test Plan: Added `testCopyBackedTextInputPreservesReturnKeyType` to `React/Tests/Text/RCTTextInputUtilsTest.mm`, alongside the existing `testCopyBackedTextInputPreservesTintColor` added in #57748. It sets `returnKeyType = UIReturnKeyDone` on an `RCTUITextField`, runs `RCTCopyBackedTextInput` into an `RCTUITextView`, and asserts the value survives. The test fails without the one-line change and passes with it. Also confirmed in a production app: a multiline `TextInput` with `returnKeyType="done"` intermittently displayed the newline key, and adding this single line fixed it. Reviewed By: christophpurrer Differential Revision: D119030795 Pulled By: Abbondanzo fbshipit-source-id: 0804a0b013f23b6c4533e4bb3d11cb13df81835c
1 parent 981cd12 commit e0159c1

2 files changed

Lines changed: 12 additions & 0 deletions

File tree

‎packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputUtils.mm‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ void RCTCopyBackedTextInput(
4343
toTextInput.scrollEnabled = fromTextInput.scrollEnabled;
4444
toTextInput.secureTextEntry = fromTextInput.secureTextEntry;
4545
toTextInput.keyboardType = fromTextInput.keyboardType;
46+
toTextInput.returnKeyType = fromTextInput.returnKeyType;
4647
toTextInput.textContentType = fromTextInput.textContentType;
4748
toTextInput.smartInsertDeleteType = fromTextInput.smartInsertDeleteType;
4849
toTextInput.passwordRules = fromTextInput.passwordRules;

‎packages/react-native/React/Tests/Text/RCTTextInputUtilsTest.mm‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,15 @@ - (void)testCopyBackedTextInputPreservesTintColor
2626
XCTAssertEqualObjects(destination.tintColor, UIColor.redColor);
2727
}
2828

29+
- (void)testCopyBackedTextInputPreservesReturnKeyType
30+
{
31+
RCTUITextField *source = [RCTUITextField new];
32+
RCTUITextView *destination = [RCTUITextView new];
33+
source.returnKeyType = UIReturnKeyDone;
34+
35+
RCTCopyBackedTextInput(source, destination);
36+
37+
XCTAssertEqual(destination.returnKeyType, UIReturnKeyDone);
38+
}
39+
2940
@end

0 commit comments

Comments
 (0)