Skip to content

Commit d849a84

Browse files
committed
fix: Reset mentions when value is undefined
fix ant-design/ant-design#20407
1 parent 5dac849 commit d849a84

File tree

3 files changed

+50
-18
lines changed

3 files changed

+50
-18
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"@types/react-dom": "^16.0.11",
4545
"@types/warning": "^3.0.0",
4646
"@umijs/fabric": "^1.1.9",
47+
"enzyme": "^3.11.0",
4748
"enzyme-to-json": "^3.1.4",
4849
"father": "^2.13.6",
4950
"lodash.debounce": "^4.0.8",

src/Mentions.tsx

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,14 @@ class Mentions extends React.Component<MentionsProps, MentionsState> {
7272
rows: 1,
7373
};
7474

75-
public static getDerivedStateFromProps(props: MentionsProps, prevState: MentionsState) {
75+
public static getDerivedStateFromProps(
76+
props: MentionsProps,
77+
prevState: MentionsState,
78+
) {
7679
const newState: Partial<MentionsState> = {};
7780

7881
if ('value' in props && props.value !== prevState.value) {
79-
newState.value = props.value;
82+
newState.value = props.value || '';
8083
}
8184

8285
return newState;
@@ -115,7 +118,9 @@ class Mentions extends React.Component<MentionsProps, MentionsState> {
115118
}
116119
};
117120

118-
public onChange: React.ChangeEventHandler<HTMLTextAreaElement> = ({ target: { value } }) => {
121+
public onChange: React.ChangeEventHandler<HTMLTextAreaElement> = ({
122+
target: { value },
123+
}) => {
119124
this.triggerChange(value);
120125
};
121126

@@ -166,18 +171,23 @@ class Mentions extends React.Component<MentionsProps, MentionsState> {
166171
const { prefix = '', onSearch, validateSearch } = this.props;
167172
const target = event.target as HTMLTextAreaElement;
168173
const selectionStartText = getBeforeSelectionText(target);
169-
const { location: measureIndex, prefix: measurePrefix } = getLastMeasureIndex(
170-
selectionStartText,
171-
prefix,
172-
);
174+
const {
175+
location: measureIndex,
176+
prefix: measurePrefix,
177+
} = getLastMeasureIndex(selectionStartText, prefix);
173178

174179
// Skip if match the white key list
175-
if ([KeyCode.ESC, KeyCode.UP, KeyCode.DOWN, KeyCode.ENTER].indexOf(which) !== -1) {
180+
if (
181+
[KeyCode.ESC, KeyCode.UP, KeyCode.DOWN, KeyCode.ENTER].indexOf(which) !==
182+
-1
183+
) {
176184
return;
177185
}
178186

179187
if (measureIndex !== -1) {
180-
const measureText = selectionStartText.slice(measureIndex + measurePrefix.length);
188+
const measureText = selectionStartText.slice(
189+
measureIndex + measurePrefix.length,
190+
);
181191
const validateMeasure: boolean = validateSearch(measureText, this.props);
182192
const matchOption = !!this.getOptions(measureText).length;
183193

@@ -295,7 +305,11 @@ class Mentions extends React.Component<MentionsProps, MentionsState> {
295305
return list;
296306
};
297307

298-
public startMeasure(measureText: string, measurePrefix: string, measureLocation: number) {
308+
public startMeasure(
309+
measureText: string,
310+
measurePrefix: string,
311+
measureLocation: number,
312+
) {
299313
this.setState({
300314
measuring: true,
301315
measureText,
@@ -325,7 +339,13 @@ class Mentions extends React.Component<MentionsProps, MentionsState> {
325339
}
326340

327341
public render() {
328-
const { value, measureLocation, measurePrefix, measuring, activeIndex } = this.state;
342+
const {
343+
value,
344+
measureLocation,
345+
measurePrefix,
346+
measuring,
347+
activeIndex,
348+
} = this.state;
329349
const {
330350
prefixCls,
331351
placement,

tests/Mentions.spec.jsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ describe('Mentions', () => {
3232

3333
it('not lose focus if click on dropdown', () => {
3434
const onBlur = jest.fn();
35-
const wrapper = createMentions({ autoFocus: true, defaultValue: '@', onBlur });
35+
const wrapper = createMentions({
36+
autoFocus: true,
37+
defaultValue: '@',
38+
onBlur,
39+
});
3640

3741
// Inject to trigger measure
3842
wrapper.instance().startMeasure('b', '@', 1);
@@ -45,22 +49,22 @@ describe('Mentions', () => {
4549
wrapper.find('textarea').simulate('focus'); // This is not good but code focus not work in simulate
4650
jest.runAllTimers();
4751

48-
expect(onBlur).not.toBeCalled();
52+
expect(onBlur).not.toHaveBeenCalled();
4953
});
5054

5155
it('focus', () => {
5256
const onFocus = jest.fn();
5357
const wrapper = createMentions({ onFocus });
5458
wrapper.find('textarea').simulate('focus');
55-
expect(onFocus).toBeCalled();
59+
expect(onFocus).toHaveBeenCalled();
5660
});
5761

5862
it('blur', () => {
5963
const onBlur = jest.fn();
6064
const wrapper = createMentions({ onBlur });
6165
wrapper.find('textarea').simulate('blur');
6266
jest.runAllTimers();
63-
expect(onBlur).toBeCalled();
67+
expect(onBlur).toHaveBeenCalled();
6468
});
6569

6670
it('focus() & blur()', () => {
@@ -69,7 +73,9 @@ describe('Mentions', () => {
6973
expect(document.activeElement).toBe(wrapper.find('textarea').instance());
7074

7175
wrapper.instance().blur();
72-
expect(document.activeElement).not.toBe(wrapper.find('textarea').instance());
76+
expect(document.activeElement).not.toBe(
77+
wrapper.find('textarea').instance(),
78+
);
7379
});
7480
});
7581

@@ -85,6 +91,9 @@ describe('Mentions', () => {
8591

8692
wrapper.setProps({ value: 'cat' });
8793
expect(wrapper.find('textarea').props().value).toBe('cat');
94+
95+
wrapper.setProps({ value: undefined });
96+
expect(wrapper.find('textarea').props().value).toBe('');
8897
});
8998

9099
it('onChange', () => {
@@ -93,7 +102,7 @@ describe('Mentions', () => {
93102
wrapper.find('textarea').simulate('change', {
94103
target: { value: 'bamboo' },
95104
});
96-
expect(onChange).toBeCalledWith('bamboo');
105+
expect(onChange).toHaveBeenCalledWith('bamboo');
97106
});
98107
});
99108

@@ -105,7 +114,9 @@ describe('Mentions', () => {
105114
});
106115

107116
it('function', () => {
108-
const wrapper = createMentions({ filterOption: (_, { value }) => value.includes('a') });
117+
const wrapper = createMentions({
118+
filterOption: (_, { value }) => value.includes('a'),
119+
});
109120
simulateInput(wrapper, '@notExist');
110121
expect(wrapper.find('DropdownMenu').props().options.length).toBe(2);
111122
});

0 commit comments

Comments
 (0)