Skip to content

[Fabric] Fix onChangeText firing twice when first typing in TextInput #14786

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
789a853
Initial plan for issue
Copilot Jun 16, 2025
d3d95af
Initial analysis: Identify double onChange event in Fabric TextInput
Copilot Jun 16, 2025
1ec1f5a
Fix double onChange event in Fabric TextInput by checking m_comingFro…
Copilot Jun 16, 2025
7e50ec1
Change files
Copilot Jun 16, 2025
fecc3ef
Remove unnecessary codegen file changes unrelated to TextInput fix
Copilot Jun 16, 2025
d48bdb9
Improve TextInput onChange fix with text-based deduplication
Copilot Jun 17, 2025
1b22de5
Revert unrelated codegen changes from TextInput fix
Copilot Jun 17, 2025
f00f563
Replace expensive string comparison with code flow check using m_comi…
Copilot Jun 18, 2025
cecdb31
Improve TextInput onChange fix using event count comparison instead o…
Copilot Jun 18, 2025
0dec8fa
Remove unrelated codegen changes from TextInput onChange fix
Copilot Jun 18, 2025
5673dc3
Fix event count initialization issue in TextInput onChange
Copilot Jun 18, 2025
febb163
Fix TextInput onChange using RichEdit modify flag instead of state co…
Copilot Jun 26, 2025
508ae41
Revert to simple RichEdit modify flag approach as requested
Copilot Jun 26, 2025
2436584
Merge branch 'main' into copilot/fix-12780
HariniMalothu17 Jun 26, 2025
cb21247
Fix TextInput onChange double event issue using consistent m_comingFr…
Copilot Jun 26, 2025
2938058
Remove unnecessary codegen file changes, keep only essential TextInpu…
Copilot Jun 26, 2025
21e0c91
Fix TextInput onChange double firing using RichEdit modify flag approach
Copilot Jun 26, 2025
2c5e5d8
Simplify TextInput onChange fix to minimal approach, remove unnecessa…
Copilot Jun 26, 2025
6eb444c
Fresh fix for TextInput onChange double firing using improved RichEdi…
Copilot Jun 30, 2025
3cb971b
Restore GetContentSize and autoFocus functionality with minimal onCha…
Copilot Jun 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 56 additions & 56 deletions vnext/codegen/rnwcoreJSI-generated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,41 +946,6 @@ NativeAnimatedTurboModuleCxxSpecJSI::NativeAnimatedTurboModuleCxxSpecJSI(std::sh
methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleCxxSpecJSI_removeListeners};
methodMap_["queueAndExecuteBatchedOperations"] = MethodMetadata {1, __hostFunction_NativeAnimatedTurboModuleCxxSpecJSI_queueAndExecuteBatchedOperations};
}
static jsi::Value __hostFunction_NativeAppearanceCxxSpecJSI_getColorScheme(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot what's the purpose of this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes in the codegen file were unintentional and unrelated to the TextInput fix. They were just code reordering without functional changes. I've removed these unnecessary changes in commit fecc3ef - the actual fix only needs the one-line change in WindowsTextInputComponentView.cpp.

auto result = static_cast<NativeAppearanceCxxSpecJSI *>(&turboModule)->getColorScheme(
rt
);
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
}
static jsi::Value __hostFunction_NativeAppearanceCxxSpecJSI_setColorScheme(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeAppearanceCxxSpecJSI *>(&turboModule)->setColorScheme(
rt,
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeAppearanceCxxSpecJSI_addListener(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeAppearanceCxxSpecJSI *>(&turboModule)->addListener(
rt,
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeAppearanceCxxSpecJSI_removeListeners(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeAppearanceCxxSpecJSI *>(&turboModule)->removeListeners(
rt,
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asNumber()
);
return jsi::Value::undefined();
}

NativeAppearanceCxxSpecJSI::NativeAppearanceCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("Appearance", jsInvoker) {
methodMap_["getColorScheme"] = MethodMetadata {0, __hostFunction_NativeAppearanceCxxSpecJSI_getColorScheme};
methodMap_["setColorScheme"] = MethodMetadata {1, __hostFunction_NativeAppearanceCxxSpecJSI_setColorScheme};
methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAppearanceCxxSpecJSI_addListener};
methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAppearanceCxxSpecJSI_removeListeners};
}
static jsi::Value __hostFunction_NativeAppStateCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeAppStateCxxSpecJSI *>(&turboModule)->getConstants(
rt
Expand Down Expand Up @@ -1026,6 +991,41 @@ NativeAppThemeCxxSpecJSI::NativeAppThemeCxxSpecJSI(std::shared_ptr<CallInvoker>
: TurboModule("AppTheme", jsInvoker) {
methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeAppThemeCxxSpecJSI_getConstants};
}
static jsi::Value __hostFunction_NativeAppearanceCxxSpecJSI_getColorScheme(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
auto result = static_cast<NativeAppearanceCxxSpecJSI *>(&turboModule)->getColorScheme(
rt
);
return result ? jsi::Value(std::move(*result)) : jsi::Value::null();
}
static jsi::Value __hostFunction_NativeAppearanceCxxSpecJSI_setColorScheme(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeAppearanceCxxSpecJSI *>(&turboModule)->setColorScheme(
rt,
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeAppearanceCxxSpecJSI_addListener(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeAppearanceCxxSpecJSI *>(&turboModule)->addListener(
rt,
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt)
);
return jsi::Value::undefined();
}
static jsi::Value __hostFunction_NativeAppearanceCxxSpecJSI_removeListeners(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeAppearanceCxxSpecJSI *>(&turboModule)->removeListeners(
rt,
count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asNumber()
);
return jsi::Value::undefined();
}

NativeAppearanceCxxSpecJSI::NativeAppearanceCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("Appearance", jsInvoker) {
methodMap_["getColorScheme"] = MethodMetadata {0, __hostFunction_NativeAppearanceCxxSpecJSI_getColorScheme};
methodMap_["setColorScheme"] = MethodMetadata {1, __hostFunction_NativeAppearanceCxxSpecJSI_setColorScheme};
methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAppearanceCxxSpecJSI_addListener};
methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAppearanceCxxSpecJSI_removeListeners};
}
static jsi::Value __hostFunction_NativeBlobModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeBlobModuleCxxSpecJSI *>(&turboModule)->getConstants(
rt
Expand Down Expand Up @@ -1129,27 +1129,6 @@ NativeClipboardCxxSpecJSI::NativeClipboardCxxSpecJSI(std::shared_ptr<CallInvoker
methodMap_["getString"] = MethodMetadata {0, __hostFunction_NativeClipboardCxxSpecJSI_getString};
methodMap_["setString"] = MethodMetadata {1, __hostFunction_NativeClipboardCxxSpecJSI_setString};
}
static jsi::Value __hostFunction_NativeDeviceEventManagerCxxSpecJSI_invokeDefaultBackPressHandler(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeDeviceEventManagerCxxSpecJSI *>(&turboModule)->invokeDefaultBackPressHandler(
rt
);
return jsi::Value::undefined();
}

NativeDeviceEventManagerCxxSpecJSI::NativeDeviceEventManagerCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("DeviceEventManager", jsInvoker) {
methodMap_["invokeDefaultBackPressHandler"] = MethodMetadata {0, __hostFunction_NativeDeviceEventManagerCxxSpecJSI_invokeDefaultBackPressHandler};
}
static jsi::Value __hostFunction_NativeDeviceInfoCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeDeviceInfoCxxSpecJSI *>(&turboModule)->getConstants(
rt
);
}

NativeDeviceInfoCxxSpecJSI::NativeDeviceInfoCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("DeviceInfo", jsInvoker) {
methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeDeviceInfoCxxSpecJSI_getConstants};
}
static jsi::Value __hostFunction_NativeDevLoadingViewCxxSpecJSI_showMessage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeDevLoadingViewCxxSpecJSI *>(&turboModule)->showMessage(
rt,
Expand Down Expand Up @@ -1293,6 +1272,27 @@ NativeDevSettingsCxxSpecJSI::NativeDevSettingsCxxSpecJSI(std::shared_ptr<CallInv
methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeDevSettingsCxxSpecJSI_removeListeners};
methodMap_["setIsShakeToShowDevMenuEnabled"] = MethodMetadata {1, __hostFunction_NativeDevSettingsCxxSpecJSI_setIsShakeToShowDevMenuEnabled};
}
static jsi::Value __hostFunction_NativeDeviceEventManagerCxxSpecJSI_invokeDefaultBackPressHandler(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
static_cast<NativeDeviceEventManagerCxxSpecJSI *>(&turboModule)->invokeDefaultBackPressHandler(
rt
);
return jsi::Value::undefined();
}

NativeDeviceEventManagerCxxSpecJSI::NativeDeviceEventManagerCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("DeviceEventManager", jsInvoker) {
methodMap_["invokeDefaultBackPressHandler"] = MethodMetadata {0, __hostFunction_NativeDeviceEventManagerCxxSpecJSI_invokeDefaultBackPressHandler};
}
static jsi::Value __hostFunction_NativeDeviceInfoCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeDeviceInfoCxxSpecJSI *>(&turboModule)->getConstants(
rt
);
}

NativeDeviceInfoCxxSpecJSI::NativeDeviceInfoCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("DeviceInfo", jsInvoker) {
methodMap_["getConstants"] = MethodMetadata {0, __hostFunction_NativeDeviceInfoCxxSpecJSI_getConstants};
}
static jsi::Value __hostFunction_NativeDialogManagerAndroidCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
return static_cast<NativeDialogManagerAndroidCxxSpecJSI *>(&turboModule)->getConstants(
rt
Expand Down
Loading