Skip to content

Commit ee4f474

Browse files
fix: search input unresponsive when notFoundContent is null and no options match
When notFoundContent is null and search yields no matching options, the search input was immediately clearing typed characters. Root cause: The useEffect that clears searchValue on dropdown close was triggering even when the dropdown was forced closed by emptyListContent, not from an actual user close action. Fix: Track the previous open state and emptyListContent via refs. Only clear searchValue when the dropdown was actually open before and emptyListContent is not preventing the dropdown from showing. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent a3ffbcf commit ee4f474

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

src/BaseSelect/index.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,10 +431,26 @@ const BaseSelect = React.forwardRef<BaseSelectRef, BaseSelectProps>((props, ref)
431431
};
432432

433433
// Close will clean up single mode search text
434+
// Use ref to avoid adding emptyListContent to dependencies
435+
const emptyListContentRef = React.useRef(emptyListContent);
436+
emptyListContentRef.current = emptyListContent;
437+
438+
const prevOpenRef = React.useRef(mergedOpen);
434439
React.useEffect(() => {
435-
if (!mergedOpen && !multiple && mode !== 'combobox') {
440+
// Only clean search value when dropdown actually closes (true -> false)
441+
// Skip when emptyListContent is true - this means dropdown was forced closed
442+
// due to no matching options and notFoundContent being null,
443+
// user should still be able to continue typing
444+
if (
445+
prevOpenRef.current &&
446+
!mergedOpen &&
447+
!multiple &&
448+
mode !== 'combobox' &&
449+
!emptyListContentRef.current
450+
) {
436451
onInternalSearch('', false, false);
437452
}
453+
prevOpenRef.current = mergedOpen;
438454
}, [mergedOpen]);
439455

440456
// ============================ Disabled ============================

tests/Select.test.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,6 +1997,35 @@ describe('Select.Basic', () => {
19971997
expect(container.querySelector('.rc-select-dropdown-empty')).toBeFalsy();
19981998
});
19991999

2000+
// https://github.com/react-component/select/issues/XXX
2001+
it('should allow typing when notFoundContent is null and no options match', () => {
2002+
const onSearch = jest.fn();
2003+
const { container } = render(
2004+
<Select showSearch notFoundContent={null} onSearch={onSearch}>
2005+
<Option value="jack">Jack</Option>
2006+
<Option value="lucy">Lucy</Option>
2007+
</Select>,
2008+
);
2009+
2010+
const input = container.querySelector('input');
2011+
2012+
// Type 'j' - should match 'Jack'
2013+
fireEvent.change(input, { target: { value: 'j' } });
2014+
expect(onSearch).toHaveBeenLastCalledWith('j');
2015+
expect(input.value).toBe('j');
2016+
expect(container.querySelectorAll('.rc-select-item-option')).toHaveLength(1);
2017+
2018+
// Type 'x' - no match, but input should still work
2019+
fireEvent.change(input, { target: { value: 'x' } });
2020+
expect(onSearch).toHaveBeenLastCalledWith('x');
2021+
expect(input.value).toBe('x');
2022+
2023+
// Type more characters - should continue working
2024+
fireEvent.change(input, { target: { value: 'xyz' } });
2025+
expect(onSearch).toHaveBeenLastCalledWith('xyz');
2026+
expect(input.value).toBe('xyz');
2027+
});
2028+
20002029
it('click outside to close select', () => {
20012030
jest.useFakeTimers();
20022031

0 commit comments

Comments
 (0)