From 91d4caca7b7d08c5316d2c54726a55b98cbc0c9c Mon Sep 17 00:00:00 2001 From: jingzouzou <827088092@qq.com> Date: Tue, 15 Oct 2024 00:35:01 +0800 Subject: [PATCH 01/10] fix: should not pass `loadData` when expandedKeys is not changed, whick avoid triggering all nodes load data --- src/OptionList.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index 2d627c1d..6c103ef7 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -196,6 +196,16 @@ const OptionList: React.ForwardRefRenderFunction = (_, onKeyUp: () => {}, })); + + const loadDataFun = React.useMemo(() => { + // should not pass `loadData` when expandedKeys is not changed + if (!searchValue && searchExpandedKeys?.length && !mergedExpandedKeys) { + return null + } + + return searchValue ? null : (loadData as any) + }, [searchValue]) + // ========================== Render ========================== if (memoTreeData.length === 0) { return ( @@ -237,7 +247,7 @@ const OptionList: React.ForwardRefRenderFunction = (_, showIcon={showTreeIcon} switcherIcon={switcherIcon} showLine={treeLine} - loadData={searchValue ? null : (loadData as any)} + loadData={loadDataFun} motion={treeMotion} activeKey={activeKey} // We handle keys by out instead tree self From 1f79277c8511624e8eebb0ff39a27c41cd1cfca5 Mon Sep 17 00:00:00 2001 From: jingzouzou <827088092@qq.com> Date: Fri, 18 Oct 2024 21:21:15 +0800 Subject: [PATCH 02/10] feat: add test cases --- tests/Select.SearchInput.spec.js | 113 ++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/tests/Select.SearchInput.spec.js b/tests/Select.SearchInput.spec.js index 694d5521..259d90cf 100644 --- a/tests/Select.SearchInput.spec.js +++ b/tests/Select.SearchInput.spec.js @@ -1,7 +1,7 @@ /* eslint-disable no-undef */ import React, { useState } from 'react'; import { mount } from 'enzyme'; -import TreeSelect, { TreeNode } from '../src'; +import TreeSelect, { TreeNode, TreeSelectProps } from '../src'; describe('TreeSelect.SearchInput', () => { it('select item will clean searchInput', () => { @@ -19,12 +19,7 @@ describe('TreeSelect.SearchInput', () => { wrapper.selectNode(); expect(onSearch).not.toHaveBeenCalled(); - expect( - wrapper - .find('input') - .first() - .props().value, - ).toBeFalsy(); + expect(wrapper.find('input').first().props().value).toBeFalsy(); }); it('expandedKeys', () => { @@ -51,10 +46,7 @@ describe('TreeSelect.SearchInput', () => { expect(wrapper.find('NodeList').prop('expandedKeys')).toEqual(['bamboo', 'light']); function search(value) { - wrapper - .find('input') - .first() - .simulate('change', { target: { value } }); + wrapper.find('input').first().simulate('change', { target: { value } }); wrapper.update(); } @@ -85,8 +77,8 @@ describe('TreeSelect.SearchInput', () => { { id: 1, pId: 0, value: '1', title: 'Expand to load' }, { id: 2, pId: 0, value: '2', title: 'Expand to load' }, { id: 3, pId: 0, value: '3', title: 'Tree Node', isLeaf: true }, - ]) - } + ]); + }; const genTreeNode = (parentId, isLeaf = false) => { const random = Math.random().toString(36).substring(2, 6); @@ -100,22 +92,16 @@ describe('TreeSelect.SearchInput', () => { }; const onLoadData = ({ id, ...rest }) => - new Promise((resolve) => { - setTimeout(() => { - called += 1; - handleLoadData({ id, ...rest }); - setTreeData( - treeData.concat([ - genTreeNode(id, false), - genTreeNode(id, true), - genTreeNode(id, true), - ]) - ); - resolve(undefined); - }, 300); + new Promise(resolve => { + called += 1; + handleLoadData({ id, ...rest }); + setTreeData( + treeData.concat([genTreeNode(id, false), genTreeNode(id, true), genTreeNode(id, true)]), + ); + resolve(undefined); }); - const onChange = (newValue) => { + const onChange = newValue => { setValue(newValue); }; @@ -130,7 +116,6 @@ describe('TreeSelect.SearchInput', () => { treeData={treeData} treeNodeFilterProp="title" showSearch - filterTreeNode={false} /> @@ -141,10 +126,7 @@ describe('TreeSelect.SearchInput', () => { expect(handleLoadData).not.toHaveBeenCalled(); function search(value) { - wrapper - .find('input') - .first() - .simulate('change', { target: { value } }); + wrapper.find('input').first().simulate('change', { target: { value } }); wrapper.update(); } search('Tree Node'); @@ -165,5 +147,72 @@ describe('TreeSelect.SearchInput', () => { search(''); expect(handleLoadData).not.toHaveBeenCalled(); expect(called).toBe(0); + + search('ex'); + const nodes = wrapper.find(`[title="${'Expand to load'}"]`).hostNodes(); + nodes.first().simulate('click'); + expect(called).toBe(0); // should not trrigger all nodes to load data + }); + + it('not trigger loadData when clearing the search', () => { + let called = 0; + const handleLoadData = jest.fn(); + const Demo = () => { + const [value, setValue] = useState(); + + const genTreeNode = (parentId, isLeaf = false) => { + const random = Math.random().toString(36).substring(2, 6); + return { + id: random, + pId: parentId, + value: random, + title: isLeaf ? 'Tree Node' : 'Expand to load', + isLeaf, + }; + }; + + const onLoadData = ({ id, ...rest }) => + new Promise(resolve => { + called += 1; + handleLoadData({ id, ...rest }); + setTreeData( + treeData.concat([genTreeNode(id, false), genTreeNode(id, true), genTreeNode(id, true)]), + ); + resolve(undefined); + }); + + const onChange = newValue => { + setValue(newValue); + }; + + return ( + + ); + }; + const wrapper = mount(); + + function search(value) { + wrapper.find('input').first().simulate('change', { target: { value } }); + wrapper.update(); + } + + search('ex'); + const nodes = wrapper.find(`[title="${'Expand to load'}"]`).hostNodes(); + nodes.first().simulate('click'); + expect(called).toBe(1); }); }); From 9a2ef310b2f77937cfe16ddc40408617b4a8513b Mon Sep 17 00:00:00 2001 From: jingzouzou <827088092@qq.com> Date: Fri, 18 Oct 2024 21:28:27 +0800 Subject: [PATCH 03/10] chore: add all dependencies to loadDataFun --- src/OptionList.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index e7d89c72..939b1e3d 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -196,15 +196,14 @@ const OptionList: React.ForwardRefRenderFunction = (_, onKeyUp: () => {}, })); - const loadDataFun = React.useMemo(() => { // should not pass `loadData` when expandedKeys is not changed if (!searchValue && searchExpandedKeys?.length && !mergedExpandedKeys) { - return null + return null; } - return searchValue ? null : (loadData as any) - }, [searchValue]) + return searchValue ? null : (loadData as any); + }, [searchValue, searchExpandedKeys?.length, mergedExpandedKeys, loadData]); // ========================== Render ========================== if (memoTreeData.length === 0) { From ce94a41a96d6817408cb5dd4dce067f4b85df253 Mon Sep 17 00:00:00 2001 From: jingzouzou <827088092@qq.com> Date: Fri, 18 Oct 2024 21:39:20 +0800 Subject: [PATCH 04/10] chore: optimize test cases --- tests/Select.SearchInput.spec.js | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/tests/Select.SearchInput.spec.js b/tests/Select.SearchInput.spec.js index 259d90cf..e859c2a9 100644 --- a/tests/Select.SearchInput.spec.js +++ b/tests/Select.SearchInput.spec.js @@ -1,7 +1,7 @@ /* eslint-disable no-undef */ import React, { useState } from 'react'; import { mount } from 'enzyme'; -import TreeSelect, { TreeNode, TreeSelectProps } from '../src'; +import TreeSelect, { TreeNode } from '../src'; describe('TreeSelect.SearchInput', () => { it('select item will clean searchInput', () => { @@ -154,30 +154,13 @@ describe('TreeSelect.SearchInput', () => { expect(called).toBe(0); // should not trrigger all nodes to load data }); - it('not trigger loadData when clearing the search', () => { + it('should trrigger `loadData` when click node', () => { let called = 0; - const handleLoadData = jest.fn(); const Demo = () => { const [value, setValue] = useState(); - - const genTreeNode = (parentId, isLeaf = false) => { - const random = Math.random().toString(36).substring(2, 6); - return { - id: random, - pId: parentId, - value: random, - title: isLeaf ? 'Tree Node' : 'Expand to load', - isLeaf, - }; - }; - const onLoadData = ({ id, ...rest }) => new Promise(resolve => { called += 1; - handleLoadData({ id, ...rest }); - setTreeData( - treeData.concat([genTreeNode(id, false), genTreeNode(id, true), genTreeNode(id, true)]), - ); resolve(undefined); }); From 8acc1c8d7497b9fa1ba65bc0e500197abc1ff317 Mon Sep 17 00:00:00 2001 From: jingzouzou <827088092@qq.com> Date: Mon, 21 Oct 2024 19:00:54 +0800 Subject: [PATCH 05/10] feat: optimize `loadDataFun`'s calculation --- src/OptionList.tsx | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index 939b1e3d..e02fad98 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -196,14 +196,25 @@ const OptionList: React.ForwardRefRenderFunction = (_, onKeyUp: () => {}, })); - const loadDataFun = React.useMemo(() => { - // should not pass `loadData` when expandedKeys is not changed - if (!searchValue && searchExpandedKeys?.length && !mergedExpandedKeys) { - return null; - } - - return searchValue ? null : (loadData as any); - }, [searchValue, searchExpandedKeys?.length, mergedExpandedKeys, loadData]); + const loadDataFun = useMemo( + () => { + return searchValue ? null : (loadData as any); + }, + [searchValue, treeExpandedKeys || expandedKeys], + (pre, next) => { + const [preSearchValue] = pre; + const [nextSearchValue, nextExcludeSearchExpandedKeys] = next; + + if (preSearchValue !== nextSearchValue) { + // should not pass `loadData` when expandedKeys is not changed + if (!nextSearchValue && !nextExcludeSearchExpandedKeys) { + return false; + } + return true; + } + return false; + }, + ); // ========================== Render ========================== if (memoTreeData.length === 0) { From dccd5d23d47c1fc2430c8f3d4b63231d36d53c44 Mon Sep 17 00:00:00 2001 From: jingzouzou <827088092@qq.com> Date: Tue, 22 Oct 2024 22:30:51 +0800 Subject: [PATCH 06/10] feat: simplify `loadDataFun`'s logic --- src/OptionList.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index e02fad98..4f21a777 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -205,14 +205,14 @@ const OptionList: React.ForwardRefRenderFunction = (_, const [preSearchValue] = pre; const [nextSearchValue, nextExcludeSearchExpandedKeys] = next; - if (preSearchValue !== nextSearchValue) { + if ( + preSearchValue === nextSearchValue || // should not pass `loadData` when expandedKeys is not changed - if (!nextSearchValue && !nextExcludeSearchExpandedKeys) { - return false; - } - return true; + (!nextSearchValue && !nextExcludeSearchExpandedKeys) + ) { + return false; } - return false; + return true; }, ); From b0e20bf8363911c74a3e783a2e58930eb4666783 Mon Sep 17 00:00:00 2001 From: jingzouzou Date: Wed, 23 Oct 2024 20:42:19 +0800 Subject: [PATCH 07/10] chore: delete notes and change logic --- src/OptionList.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index 4f21a777..ef41f262 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -205,14 +205,9 @@ const OptionList: React.ForwardRefRenderFunction = (_, const [preSearchValue] = pre; const [nextSearchValue, nextExcludeSearchExpandedKeys] = next; - if ( - preSearchValue === nextSearchValue || - // should not pass `loadData` when expandedKeys is not changed - (!nextSearchValue && !nextExcludeSearchExpandedKeys) - ) { - return false; - } - return true; + return ( + preSearchValue !== nextSearchValue && !!(nextSearchValue || nextExcludeSearchExpandedKeys) + ); }, ); From 471df43dafbbd165b2d8e45c16ee55cf2ce95ab1 Mon Sep 17 00:00:00 2001 From: AKing <827088092@qq.com> Date: Wed, 23 Oct 2024 22:25:51 +0800 Subject: [PATCH 08/10] simplify `loadDataFun` return Co-authored-by: afc163 --- src/OptionList.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index ef41f262..1d47b91b 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -197,9 +197,7 @@ const OptionList: React.ForwardRefRenderFunction = (_, })); const loadDataFun = useMemo( - () => { - return searchValue ? null : (loadData as any); - }, + () => searchValue ? null : (loadData as any), [searchValue, treeExpandedKeys || expandedKeys], (pre, next) => { const [preSearchValue] = pre; From 729c61351fdd91f0e2cbcd588a55e42838ebab2c Mon Sep 17 00:00:00 2001 From: AKing <827088092@qq.com> Date: Wed, 23 Oct 2024 22:26:29 +0800 Subject: [PATCH 09/10] simplify `loadDataFun` change logic Co-authored-by: afc163 --- src/OptionList.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index 1d47b91b..2d53d281 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -199,14 +199,8 @@ const OptionList: React.ForwardRefRenderFunction = (_, const loadDataFun = useMemo( () => searchValue ? null : (loadData as any), [searchValue, treeExpandedKeys || expandedKeys], - (pre, next) => { - const [preSearchValue] = pre; - const [nextSearchValue, nextExcludeSearchExpandedKeys] = next; - - return ( - preSearchValue !== nextSearchValue && !!(nextSearchValue || nextExcludeSearchExpandedKeys) - ); - }, + ([preSearchValue], [nextSearchValue, nextExcludeSearchExpandedKeys]) => + preSearchValue !== nextSearchValue && (nextSearchValue || nextExcludeSearchExpandedKeys) ); // ========================== Render ========================== From cf496e4008f363f49ceb01fb0ebb2208c8444ba5 Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 24 Oct 2024 10:02:23 +0800 Subject: [PATCH 10/10] Update src/OptionList.tsx --- src/OptionList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OptionList.tsx b/src/OptionList.tsx index 2d53d281..10e99760 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -200,7 +200,7 @@ const OptionList: React.ForwardRefRenderFunction = (_, () => searchValue ? null : (loadData as any), [searchValue, treeExpandedKeys || expandedKeys], ([preSearchValue], [nextSearchValue, nextExcludeSearchExpandedKeys]) => - preSearchValue !== nextSearchValue && (nextSearchValue || nextExcludeSearchExpandedKeys) + preSearchValue !== nextSearchValue && !!(nextSearchValue || nextExcludeSearchExpandedKeys) ); // ========================== Render ==========================