fix(input): Improve resolveOnChange method (#31931)

* fix: Improve input resolveOnChange method

* fix(input): add test case for allowClear
This commit is contained in:
Aex 2021-08-30 13:25:32 +08:00 committed by GitHub
parent af805c098b
commit 01e53132b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 77 additions and 11 deletions

View File

@ -75,18 +75,30 @@ export function resolveOnChange<E extends HTMLInputElement | HTMLTextAreaElement
return;
}
let event = e;
const originalInputValue = target.value;
if (e.type === 'click') {
// click clear icon
event = Object.create(e);
event.target = target;
event.currentTarget = target;
// change target ref value cause e.target.value should be '' when clear input
target.value = '';
// Clone a new target for event.
// Avoid the following usage, the setQuery method gets the original value.
//
// const [query, setQuery] = React.useState('');
// <Input
// allowClear
// value={query}
// onChange={(e)=> {
// setQuery((prevStatus) => e.target.value);
// }}
// />
const currentTarget = target.cloneNode(true) as E;
event.target = currentTarget;
event.currentTarget = currentTarget;
currentTarget.value = '';
onChange(event as React.ChangeEvent<E>);
// reset target ref value
target.value = originalInputValue;
return;
}

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { mount } from 'enzyme';
// eslint-disable-next-line import/no-unresolved
import Form from '../../form';
@ -228,4 +228,31 @@ describe('Input allowClear', () => {
expect(onBlur).not.toBeCalled();
wrapper.unmount();
});
// https://github.com/ant-design/ant-design/issues/31927
it('should correctly when useState', () => {
const App = () => {
const [query, setQuery] = useState('');
return (
<Input
allowClear
value={query}
onChange={e => {
setQuery(() => e.target.value);
}}
/>
);
};
const wrapper = mount(<App />);
wrapper.find('input').getDOMNode().focus();
wrapper.find('input').simulate('change', { target: { value: '111' } });
expect(wrapper.find('input').getDOMNode().value).toEqual('111');
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
expect(wrapper.find('input').getDOMNode().value).toEqual('');
wrapper.unmount();
});
});

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { mount } from 'enzyme';
import RcTextArea from 'rc-textarea';
import Input from '..';
@ -380,14 +380,14 @@ describe('TextArea allowClear', () => {
expect(wrapper.find('textarea').at(0).getDOMNode().value).toBe('Light');
});
it('onChange event should return HTMLInputElement', () => {
it('onChange event should return HTMLTextAreaElement', () => {
const onChange = jest.fn();
const wrapper = mount(<Input.TextArea onChange={onChange} allowClear />);
function isNativeElement() {
expect(onChange).toHaveBeenCalledWith(
expect.objectContaining({
target: wrapper.find('textarea').instance(),
target: expect.any(HTMLTextAreaElement),
}),
);
@ -411,4 +411,31 @@ describe('TextArea allowClear', () => {
wrapper.find('.ant-input-clear-icon').first().simulate('click');
isNativeElement();
});
// https://github.com/ant-design/ant-design/issues/31927
it('should correctly when useState', () => {
const App = () => {
const [query, setQuery] = useState('');
return (
<TextArea
allowClear
value={query}
onChange={e => {
setQuery(() => e.target.value);
}}
/>
);
};
const wrapper = mount(<App />);
wrapper.find('textarea').getDOMNode().focus();
wrapper.find('textarea').simulate('change', { target: { value: '111' } });
expect(wrapper.find('textarea').getDOMNode().value).toEqual('111');
wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
expect(wrapper.find('textarea').getDOMNode().value).toEqual('');
wrapper.unmount();
});
});