Skip to content

Commit 5c2d528

Browse files
committed
fix: trigger onChange twice when inputting using the input method
1 parent 9640649 commit 5c2d528

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

src/Input.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ const Input = forwardRef<InputRef, InputProps>((props, ref) => {
9797
| React.ChangeEvent<HTMLInputElement>
9898
| React.CompositionEvent<HTMLInputElement>,
9999
currentValue: string,
100+
fromCompositionEnd?: boolean,
100101
) => {
101102
let cutValue = currentValue;
102103

@@ -116,6 +117,10 @@ const Input = forwardRef<InputRef, InputProps>((props, ref) => {
116117
inputRef.current?.selectionEnd || 0,
117118
]);
118119
}
120+
} else if (fromCompositionEnd) {
121+
// Avoid triggering twice
122+
// https://github.com/ant-design/ant-design/issues/46587
123+
return;
119124
}
120125
setValue(cutValue);
121126

@@ -138,7 +143,7 @@ const Input = forwardRef<InputRef, InputProps>((props, ref) => {
138143
e: React.CompositionEvent<HTMLInputElement>,
139144
) => {
140145
compositionRef.current = false;
141-
triggerChange(e, e.currentTarget.value);
146+
triggerChange(e, e.currentTarget.value, true);
142147
onCompositionEnd?.(e);
143148
};
144149

tests/count.test.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,45 @@ describe('Input.Count', () => {
109109
expect(setSelectionRange).toHaveBeenCalledWith(2, 2);
110110
});
111111

112+
it('input using the input method should trigger onChange once', () => {
113+
const onChange = jest.fn();
114+
const { container } = render(<Input onChange={onChange} />);
115+
const input = container.querySelector('input')!;
116+
fireEvent.compositionStart(input);
117+
fireEvent.compositionUpdate(input, { data: '你' });
118+
fireEvent.compositionEnd(input, { data: '你好' });
119+
fireEvent.input(input, { target: { value: '你好' } });
120+
expect(onChange).toHaveBeenCalledTimes(1);
121+
});
122+
123+
it('using the input method to enter the cropped content should trigger onChange twice', () => {
124+
const onChange = jest.fn();
125+
const onCompositionEnd = jest.fn();
126+
const { container } = render(
127+
<Input
128+
count={{
129+
show: true,
130+
max: 3,
131+
exceedFormatter: (val, { max }) =>
132+
getSegments(val)
133+
.filter((seg) => seg.index + seg.segment.length <= max)
134+
.map((seg) => seg.segment)
135+
.join(''),
136+
}}
137+
onChange={onChange}
138+
onCompositionEnd={onCompositionEnd}
139+
/>,
140+
);
141+
const input = container.querySelector('input')!;
142+
fireEvent.compositionStart(input);
143+
fireEvent.compositionUpdate(input, { target: { value: '你' } });
144+
fireEvent.compositionUpdate(input, { target: { value: '你好' } });
145+
fireEvent.compositionUpdate(input, { target: { value: '你好世' } });
146+
fireEvent.compositionUpdate(input, { target: { value: '你好世界' } });
147+
fireEvent.compositionEnd(input, { target: { value: '你好世界' } });
148+
expect(input?.value).toEqual('你好世');
149+
});
150+
112151
describe('cls', () => {
113152
it('raw', () => {
114153
const { container } = render(

0 commit comments

Comments
 (0)