From b1e19477019f0e08384c868ee5ea4dbf18d6032b Mon Sep 17 00:00:00 2001 From: DuQi Date: Sat, 6 Jun 2026 12:48:45 +0800 Subject: [PATCH 1/2] fix: restore load switcher after clearing search --- src/OptionList.tsx | 20 ++++++++++++++++---- tests/Select.loadData.spec.tsx | 24 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index 05462245..d2790e26 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -133,8 +133,21 @@ const OptionList: React.ForwardRefRenderFunction = (_, if (treeExpandedKeys) { return [...treeExpandedKeys]; } - return searchValue ? searchExpandedKeys : expandedKeys; - }, [expandedKeys, searchExpandedKeys, treeExpandedKeys, searchValue]); + if (searchValue) { + return searchExpandedKeys; + } + if (searchExpandedKeys && loadData && !treeDefaultExpandAll) { + return expandedKeys || []; + } + return expandedKeys; + }, [ + expandedKeys, + searchExpandedKeys, + treeExpandedKeys, + searchValue, + loadData, + treeDefaultExpandAll, + ]); const onInternalExpand = (keys: Key[]) => { setExpandedKeys(keys); @@ -310,8 +323,7 @@ const OptionList: React.ForwardRefRenderFunction = (_, () => (searchValue ? false : true), // eslint-disable-next-line react-hooks/exhaustive-deps [searchValue, treeExpandedKeys || expandedKeys], - ([preSearchValue], [nextSearchValue, nextExcludeSearchExpandedKeys]) => - preSearchValue !== nextSearchValue && !!(nextSearchValue || nextExcludeSearchExpandedKeys), + ([preSearchValue], [nextSearchValue]) => preSearchValue !== nextSearchValue, ); const syncLoadData = hasLoadDataFn ? loadData : null; diff --git a/tests/Select.loadData.spec.tsx b/tests/Select.loadData.spec.tsx index c938d95c..46f2b15b 100644 --- a/tests/Select.loadData.spec.tsx +++ b/tests/Select.loadData.spec.tsx @@ -43,4 +43,28 @@ describe('TreeSelect.loadData', () => { ).toHaveLength(2 + i); } }); + + it('keeps load switcher after clearing search value', () => { + const loadData = jest.fn(() => Promise.resolve()); + const { container } = render( + , + ); + + const input = container.querySelector('input')!; + + expect(container.querySelector('.rc-tree-select-tree-switcher_close')).toBeTruthy(); + + fireEvent.change(input, { target: { value: '1' } }); + fireEvent.change(input, { target: { value: '' } }); + + expect(loadData).not.toHaveBeenCalled(); + expect(container.querySelector('.rc-tree-select-tree-switcher_close')).toBeTruthy(); + expect(container.querySelector('.rc-tree-select-tree-switcher-noop')).toBeFalsy(); + }); }); From c4fddc02f136f0ef851216b8149fc46cd29a762a Mon Sep 17 00:00:00 2001 From: DuQi Date: Sat, 6 Jun 2026 13:12:08 +0800 Subject: [PATCH 2/2] test: cover load switcher after clearing search --- src/OptionList.tsx | 3 +-- tests/Select.loadData.spec.tsx | 9 ++++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index d2790e26..ae12c47c 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -321,8 +321,7 @@ const OptionList: React.ForwardRefRenderFunction = (_, const hasLoadDataFn = useMemo( () => (searchValue ? false : true), - // eslint-disable-next-line react-hooks/exhaustive-deps - [searchValue, treeExpandedKeys || expandedKeys], + [searchValue], ([preSearchValue], [nextSearchValue]) => preSearchValue !== nextSearchValue, ); diff --git a/tests/Select.loadData.spec.tsx b/tests/Select.loadData.spec.tsx index 46f2b15b..6ed20007 100644 --- a/tests/Select.loadData.spec.tsx +++ b/tests/Select.loadData.spec.tsx @@ -44,7 +44,7 @@ describe('TreeSelect.loadData', () => { } }); - it('keeps load switcher after clearing search value', () => { + it('keeps load switcher after clearing search value', async () => { const loadData = jest.fn(() => Promise.resolve()); const { container } = render( { expect(loadData).not.toHaveBeenCalled(); expect(container.querySelector('.rc-tree-select-tree-switcher_close')).toBeTruthy(); expect(container.querySelector('.rc-tree-select-tree-switcher-noop')).toBeFalsy(); + + fireEvent.click(container.querySelector('.rc-tree-select-tree-switcher_close')!); + await act(async () => { + await Promise.resolve(); + }); + + expect(loadData).toHaveBeenCalledTimes(1); }); });