Skip to content

Commit d2d61eb

Browse files
coadometa-codesync[bot]
authored andcommitted
Align TextInput props diffing with native defaults (#59679)
Summary: Pull Request resolved: #59679 With props diffing, a prop whose value equals its C++ default is not sent when the view is created, so the C++ default has to match the state of a newly created native view. Several `AndroidTextInputProps` fields did not: - `showSoftInputOnFocus` and `allowFontScaling` defaulted to `false` in C++ but are `true` natively, so setting them to `false` from JS had no effect. - `autoCorrect` was a plain `bool` defaulting to `false`, while the native setter has three states (on, off, unset). `autoCorrect={false}` was never sent and removing the prop could not restore the platform default. It is now `std::optional<bool>` and is sent as `null` when unset. - `numberOfLines`, `textBreakStrategy` and `includeFontPadding` were each emitted twice, once from the paragraph attributes and once from a duplicate flat field, with the later one overwriting the earlier. The flat `includeFontPadding` defaulted to `false` while the native default is `true`, so removing `includeFontPadding={true}` sent `false`. These keys are now only emitted from the paragraph attributes. The flat fields are not used for layout, which reads the paragraph and text attributes, so only the props sent to the native view change. Changelog: [Android][Fixed] - Fix `TextInput` props `showSoftInputOnFocus`, `allowFontScaling`, `autoCorrect` and `includeFontPadding` being ignored or reset incorrectly when props diffing is enabled Differential Revision: D128594780
1 parent 6e8b239 commit d2d61eb

3 files changed

Lines changed: 51 additions & 20 deletions

File tree

‎packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp‎

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ AndroidTextInputProps::AndroidTextInputProps(
7575
showSoftInputOnFocus(convertRawProp(context, rawProps,
7676
"showSoftInputOnFocus",
7777
sourceProps.showSoftInputOnFocus,
78-
{false})),
78+
{true})),
7979
autoCorrect(convertRawProp(context, rawProps,
8080
"autoCorrect",
8181
sourceProps.autoCorrect,
82-
{false})),
82+
{})),
8383
allowFontScaling(convertRawProp(context, rawProps,
8484
"allowFontScaling",
8585
sourceProps.allowFontScaling,
86-
{false})),
86+
{true})),
8787
maxFontSizeMultiplier(convertRawProp(context, rawProps,
8888
"maxFontSizeMultiplier",
8989
sourceProps.maxFontSizeMultiplier,
@@ -290,7 +290,8 @@ folly::dynamic AndroidTextInputProps::getDynamic() const {
290290
props["importantForAutofill"] = importantForAutofill;
291291
props["showSoftInputOnFocus"] = showSoftInputOnFocus;
292292
props["autoCapitalize"] = autoCapitalize;
293-
props["autoCorrect"] = autoCorrect;
293+
props["autoCorrect"] =
294+
autoCorrect.has_value() ? folly::dynamic(*autoCorrect) : nullptr;
294295
props["autoFocus"] = autoFocus;
295296
props["allowFontScaling"] = allowFontScaling;
296297
props["maxFontSizeMultiplier"] = maxFontSizeMultiplier;
@@ -500,18 +501,10 @@ folly::dynamic AndroidTextInputProps::getDiffProps(
500501
result["returnKeyLabel"] = returnKeyLabel;
501502
}
502503

503-
if (numberOfLines != oldProps->numberOfLines) {
504-
result["numberOfLines"] = numberOfLines;
505-
}
506-
507504
if (disableFullscreenUI != oldProps->disableFullscreenUI) {
508505
result["disableFullscreenUI"] = disableFullscreenUI;
509506
}
510507

511-
if (textBreakStrategy != oldProps->textBreakStrategy) {
512-
result["textBreakStrategy"] = textBreakStrategy;
513-
}
514-
515508
if (inlineImageLeft != oldProps->inlineImageLeft) {
516509
result["inlineImageLeft"] = inlineImageLeft;
517510
}
@@ -529,7 +522,8 @@ folly::dynamic AndroidTextInputProps::getDiffProps(
529522
}
530523

531524
if (autoCorrect != oldProps->autoCorrect) {
532-
result["autoCorrect"] = autoCorrect;
525+
result["autoCorrect"] =
526+
autoCorrect.has_value() ? folly::dynamic(*autoCorrect) : nullptr;
533527
}
534528

535529
if (allowFontScaling != oldProps->allowFontScaling) {
@@ -608,10 +602,6 @@ folly::dynamic AndroidTextInputProps::getDiffProps(
608602
result["textAlign"] = textAlign;
609603
}
610604

611-
if (includeFontPadding != oldProps->includeFontPadding) {
612-
result["includeFontPadding"] = includeFontPadding;
613-
}
614-
615605
if (fontWeight != oldProps->fontWeight) {
616606
result["fontWeight"] = fontWeight;
617607
}

‎packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <react/renderer/attributedstring/conversions.h>
1717
#include <react/renderer/components/textinput/BaseTextInputProps.h>
1818
#include <react/renderer/components/textinput/basePrimitives.h>
19+
#include <optional>
1920
#include <unordered_map>
2021

2122
namespace facebook::react {
@@ -83,9 +84,9 @@ class AndroidTextInputProps final : public BaseTextInputProps {
8384
std::string inlineImageLeft{};
8485
int inlineImagePadding{0};
8586
std::string importantForAutofill{};
86-
bool showSoftInputOnFocus{false};
87-
bool autoCorrect{false};
88-
bool allowFontScaling{false};
87+
bool showSoftInputOnFocus{true};
88+
std::optional<bool> autoCorrect{};
89+
bool allowFontScaling{true};
8990
Float maxFontSizeMultiplier{0.0};
9091
std::string keyboardType{};
9192
std::string returnKeyType{};

‎packages/react-native/ReactCommon/react/renderer/components/textinput/tests/AndroidTextInputPropsTest.cpp‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,46 @@ TEST(AndroidTextInputPropsTest, diffPropsTargetMatchesComponentName) {
2020
AndroidTextInputShadowNode::Name());
2121
}
2222

23+
// Values equal to the C++ default are not sent on creation, so the C++ default
24+
// has to match the state of a newly created native view.
25+
TEST(AndroidTextInputPropsTest, diffSendsValuesThatDifferFromNativeDefaults) {
26+
AndroidTextInputProps props;
27+
props.showSoftInputOnFocus = false;
28+
props.allowFontScaling = false;
29+
props.autoCorrect = false;
30+
31+
auto diff = props.getDiffProps(nullptr);
32+
33+
EXPECT_EQ(diff["showSoftInputOnFocus"], false);
34+
EXPECT_EQ(diff["allowFontScaling"], false);
35+
EXPECT_EQ(diff["autoCorrect"], false);
36+
}
37+
38+
TEST(AndroidTextInputPropsTest, diffOfDefaultPropsIsEmpty) {
39+
EXPECT_TRUE(AndroidTextInputProps().getDiffProps(nullptr).empty());
40+
}
41+
42+
TEST(AndroidTextInputPropsTest, removedAutoCorrectIsSentAsNull) {
43+
AndroidTextInputProps oldProps;
44+
oldProps.autoCorrect = false;
45+
46+
auto diff = AndroidTextInputProps().getDiffProps(&oldProps);
47+
48+
ASSERT_EQ(diff.count("autoCorrect"), 1);
49+
EXPECT_TRUE(diff["autoCorrect"].isNull());
50+
}
51+
52+
// `includeFontPadding` is sent from the paragraph attributes only, whose
53+
// default matches the native default.
54+
TEST(AndroidTextInputPropsTest, removedIncludeFontPaddingIsNotSentAsFalse) {
55+
AndroidTextInputProps oldProps;
56+
oldProps.includeFontPadding = true;
57+
58+
auto diff = AndroidTextInputProps().getDiffProps(&oldProps);
59+
60+
EXPECT_EQ(diff.count("includeFontPadding"), 0);
61+
}
62+
2363
} // namespace facebook::react
2464

2565
#endif

0 commit comments

Comments
 (0)