Skip to content

Commit 6eb444c

Browse files
Fresh fix for TextInput onChange double firing using improved RichEdit modify flag approach
Co-authored-by: HariniMalothu17 <[email protected]>
1 parent 2c5e5d8 commit 6eb444c

File tree

1 file changed

+25
-9
lines changed

1 file changed

+25
-9
lines changed

vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,9 +1229,21 @@ void WindowsTextInputComponentView::updateLayoutMetrics(
12291229
m_imgHeight = newHeight;
12301230
}
12311231

1232-
12331232
// When we are notified by RichEdit that the text changed, we need to notify JS
12341233
void WindowsTextInputComponentView::OnTextUpdated() noexcept {
1234+
// Check if RichEdit says the control was modified BEFORE calling updateState
1235+
// to avoid issues where updateState might trigger another text change
1236+
LRESULT modified = 0;
1237+
bool shouldEmitOnChange = false;
1238+
if (m_eventEmitter && !m_comingFromJS) {
1239+
m_textServices->TxSendMessage(EM_GETMODIFY, 0, 0, &modified);
1240+
if (modified) {
1241+
shouldEmitOnChange = true;
1242+
// Clear the modify flag immediately to prevent duplicate events
1243+
m_textServices->TxSendMessage(EM_SETMODIFY, FALSE, 0, nullptr);
1244+
}
1245+
}
1246+
12351247
auto data = m_state->getData();
12361248
// auto newAttributedString = getAttributedString();
12371249
// if (data.attributedString == newAttributedString)
@@ -1241,7 +1253,7 @@ void WindowsTextInputComponentView::OnTextUpdated() noexcept {
12411253

12421254
m_state->updateState(std::move(data));
12431255

1244-
if (m_eventEmitter && !m_comingFromJS && !m_comingFromState) {
1256+
if (shouldEmitOnChange) {
12451257
// call onChange event
12461258
auto emitter = std::static_pointer_cast<const facebook::react::WindowsTextInputEventEmitter>(m_eventEmitter);
12471259
facebook::react::WindowsTextInputEventEmitter::OnChange onChangeArgs;
@@ -1250,6 +1262,17 @@ void WindowsTextInputComponentView::OnTextUpdated() noexcept {
12501262
emitter->onChange(onChangeArgs);
12511263
}
12521264

1265+
if (m_eventEmitter && !m_comingFromJS) {
1266+
if (windowsTextInputProps().multiline) {
1267+
auto [contentWidth, contentHeight] = GetContentSize();
1268+
auto emitter = std::static_pointer_cast<const facebook::react::WindowsTextInputEventEmitter>(m_eventEmitter);
1269+
facebook::react::WindowsTextInputEventEmitter::OnContentSizeChange onContentSizeChangeArgs;
1270+
onContentSizeChangeArgs.contentSize.width = contentWidth;
1271+
onContentSizeChangeArgs.contentSize.height = contentHeight;
1272+
emitter->onContentSizeChange(onContentSizeChangeArgs);
1273+
}
1274+
}
1275+
12531276
if (UiaClientsAreListening()) {
12541277
auto text = GetTextFromRichEdit();
12551278
winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
@@ -1322,13 +1345,6 @@ void WindowsTextInputComponentView::onMounted() noexcept {
13221345
m_propBits |= TXTBIT_CHARFORMATCHANGE;
13231346
}
13241347
InternalFinalize();
1325-
1326-
// Handle autoFocus property - focus the component when mounted if autoFocus is true
1327-
if (windowsTextInputProps().autoFocus) {
1328-
if (auto root = rootComponentView()) {
1329-
root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
1330-
}
1331-
}
13321348
}
13331349

13341350
std::optional<std::string> WindowsTextInputComponentView::getAccessiblityValue() noexcept {

0 commit comments

Comments
 (0)