From 5fa3a756a2bfa23ffd0935425a4dd25c12e2036d Mon Sep 17 00:00:00 2001 From: Ed Stead Date: Wed, 20 May 2026 05:55:23 -0700 Subject: [PATCH 1/2] fix: keep onChange target mounted when value is unchanged --- src/utils/commonUtils.ts | 19 +++++++++++++++++-- tests/index.test.tsx | 13 +++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/utils/commonUtils.ts b/src/utils/commonUtils.ts index 0ab162c..05e9eb5 100644 --- a/src/utils/commonUtils.ts +++ b/src/utils/commonUtils.ts @@ -45,6 +45,16 @@ function cloneEvent< return newEvent; } +function cloneEventWithTarget< + EventType extends React.SyntheticEvent, + Element extends HTMLInputElement | HTMLTextAreaElement, +>(event: EventType, target: Element): EventType { + return Object.create(event, { + target: { value: target }, + currentTarget: { value: target }, + }); +} + export function resolveOnChange< E extends HTMLInputElement | HTMLTextAreaElement, >( @@ -84,8 +94,13 @@ export function resolveOnChange< // https://github.com/ant-design/ant-design/issues/45737 // https://github.com/ant-design/ant-design/issues/46598 if (target.type !== 'file' && targetValue !== undefined) { - event = cloneEvent(e, target, targetValue); - onChange(event as React.ChangeEvent); + if (target.value !== targetValue) { + event = cloneEvent(e, target, targetValue); + onChange(event as React.ChangeEvent); + return; + } + + onChange(cloneEventWithTarget(e, target) as React.ChangeEvent); return; } onChange(event as React.ChangeEvent); diff --git a/tests/index.test.tsx b/tests/index.test.tsx index 5b480c6..9f5f96a 100644 --- a/tests/index.test.tsx +++ b/tests/index.test.tsx @@ -439,6 +439,19 @@ describe('Input ref', () => { expect(spySetSelectionRange).toHaveBeenCalledWith(1, 2); }); + it('onChange target should be the mounted input when value is unchanged by formatter', () => { + const onChange = jest.fn(); + const { container } = render(); + const inputEl = container.querySelector('input')!; + + fireEvent.change(inputEl, { target: { value: 'test' } }); + + const event = onChange.mock.calls[0][0]; + expect(event.target).toBe(inputEl); + expect(event.currentTarget).toBe(inputEl); + expect(document.contains(event.target)).toBe(true); + }); + it('email type not support selection', () => { const onChange = jest.fn(); const { container } = render(); From 29af184283638fea106f0c2c0dd50ec29afd54af Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 21 May 2026 19:21:41 +0800 Subject: [PATCH 2/2] Update src/utils/commonUtils.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/utils/commonUtils.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/utils/commonUtils.ts b/src/utils/commonUtils.ts index 05e9eb5..fad7d94 100644 --- a/src/utils/commonUtils.ts +++ b/src/utils/commonUtils.ts @@ -96,11 +96,10 @@ export function resolveOnChange< if (target.type !== 'file' && targetValue !== undefined) { if (target.value !== targetValue) { event = cloneEvent(e, target, targetValue); - onChange(event as React.ChangeEvent); - return; + } else { + event = cloneEventWithTarget(e, target); } - - onChange(cloneEventWithTarget(e, target) as React.ChangeEvent); + onChange(event as React.ChangeEvent); return; } onChange(event as React.ChangeEvent);