Skip to content

Commit c51d1fe

Browse files
authored
fix: Combobox click logic & open status (#458)
* fix it * lazy set open state * fix test * add one more test case * not close when autoComplete mode * add test case
1 parent a614882 commit c51d1fe

File tree

5 files changed

+52
-11
lines changed

5 files changed

+52
-11
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"classnames": "2.x",
4646
"rc-animate": "^2.10.0",
4747
"rc-trigger": "^4.0.0",
48-
"rc-util": "^4.17.0",
48+
"rc-util": "^4.20.0",
4949
"rc-virtual-list": "^1.0.0",
5050
"warning": "^4.0.3"
5151
},

src/Selector/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ const Selector: React.RefForwardingComponent<
107107
const {
108108
prefixCls,
109109
multiple,
110+
open,
111+
mode,
110112

111113
onSearch,
112114
onToggleOpen,
@@ -179,7 +181,9 @@ const Selector: React.RefForwardingComponent<
179181
event.preventDefault();
180182
}
181183

182-
onToggleOpen();
184+
if (mode !== 'combobox' || !open) {
185+
onToggleOpen();
186+
}
183187
};
184188

185189
// ================= Inner Selector ==================

src/generate.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import * as React from 'react';
1111
import KeyCode from 'rc-util/lib/KeyCode';
1212
import classNames from 'classnames';
13+
import useMergedState from 'rc-util/lib/hooks/useMergedState';
1314
import Selector, { RefSelectorProps } from './Selector';
1415
import SelectTrigger, { RefTriggerProps } from './SelectTrigger';
1516
import { RenderNode, Mode, RenderDOMFunc } from './interface';
@@ -632,21 +633,24 @@ export default function generateSelector<
632633
(mode === 'combobox' && getInputElement && getInputElement()) || null;
633634

634635
// ============================== Open ==============================
635-
const [innerOpen, setInnerOpen] = React.useState<boolean>(defaultOpen);
636-
let mergedOpen: boolean =
637-
!disabled && (open !== undefined ? open : innerOpen);
636+
const [innerOpen, setInnerOpen] = useMergedState<boolean>(undefined, {
637+
defaultValue: defaultOpen,
638+
value: open,
639+
});
640+
641+
let mergedOpen = innerOpen;
638642

639643
// Not trigger `open` in `combobox` when `notFoundContent` is empty
640644
const emptyListContent = !notFoundContent && !displayOptions.length;
641-
if (emptyListContent && mergedOpen && mode === 'combobox') {
645+
if (disabled || (emptyListContent && mergedOpen && mode === 'combobox')) {
642646
mergedOpen = false;
643647
}
644648
const triggerOpen = emptyListContent ? false : mergedOpen;
645649

646650
const onToggleOpen = (newOpen?: boolean) => {
647651
const nextOpen = newOpen !== undefined ? newOpen : !mergedOpen;
648652

649-
if (mergedOpen !== nextOpen && !disabled) {
653+
if (innerOpen !== nextOpen && !disabled) {
650654
setInnerOpen(nextOpen);
651655

652656
if (onDropdownVisibleChange) {

tests/Combobox.test.tsx

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ import {
1515
import allowClearTest from './shared/allowClearTest';
1616
import throwOptionValue from './shared/throwOptionValue';
1717

18+
async function delay(timeout = 0) {
19+
return new Promise(resolve => {
20+
setTimeout(resolve, timeout);
21+
});
22+
}
23+
1824
describe('Select.Combobox', () => {
1925
injectRunAllTimers(jest);
2026

@@ -147,7 +153,7 @@ describe('Select.Combobox', () => {
147153

148154
public render() {
149155
const options = this.state.data.map(item => (
150-
<Option key={item.key}>{item.label}</Option>
156+
<Option value={item.key}>{item.label}</Option>
151157
));
152158
return (
153159
<Select
@@ -188,7 +194,7 @@ describe('Select.Combobox', () => {
188194

189195
public render() {
190196
const options = this.state.data.map(item => (
191-
<Option key={item.key}>{item.label}</Option>
197+
<Option value={item.key}>{item.label}</Option>
192198
));
193199
return (
194200
<Select
@@ -300,7 +306,7 @@ describe('Select.Combobox', () => {
300306
return (
301307
<Select mode="combobox" onChange={this.updateOptions}>
302308
{this.state.options.map(opt => (
303-
<Option key={opt}>{opt}</Option>
309+
<Option value={opt}>{opt}</Option>
304310
))}
305311
</Select>
306312
);
@@ -369,4 +375,28 @@ describe('Select.Combobox', () => {
369375

370376
expect(wrapper.find('input').props().value).toEqual('');
371377
});
378+
379+
it('should keep close after blur', async () => {
380+
const wrapper = mount(
381+
<Select mode="combobox" notFoundContent={null}>
382+
<Option value="One">One</Option>
383+
</Select>,
384+
);
385+
386+
toggleOpen(wrapper);
387+
expectOpen(wrapper);
388+
389+
// Click again should not close popup
390+
for (let i = 0; i < 10; i += 1) {
391+
wrapper.find('input').simulate('mouseDown');
392+
wrapper.update();
393+
expectOpen(wrapper);
394+
}
395+
396+
wrapper.find('input').simulate('blur');
397+
await delay(100);
398+
399+
wrapper.update();
400+
expectOpen(wrapper, false);
401+
});
372402
});

tests/Select.test.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1465,7 +1465,7 @@ describe('Select.Basic', () => {
14651465
});
14661466

14671467
describe('disabled on open', () => {
1468-
it('should not show dropdown when oepn and disabled', () => {
1468+
it('should not show dropdown when open and disabled', () => {
14691469
const wrapper = mount(
14701470
<Select open disabled>
14711471
<Option value="1">1</Option>
@@ -1485,6 +1485,7 @@ describe('Select.Basic', () => {
14851485
toggleOpen(wrapper);
14861486
expectOpen(wrapper, true);
14871487
wrapper.setProps({ disabled: true });
1488+
wrapper.update();
14881489
expectOpen(wrapper, false);
14891490
});
14901491

@@ -1497,7 +1498,9 @@ describe('Select.Basic', () => {
14971498
);
14981499
toggleOpen(wrapper);
14991500
wrapper.setProps({ disabled: true });
1501+
wrapper.update();
15001502
wrapper.setProps({ disabled: false });
1503+
wrapper.update();
15011504
expectOpen(wrapper, false);
15021505
});
15031506
});

0 commit comments

Comments
 (0)