diff --git a/uui-core/src/data/processing/views/tree/hooks/common/index.ts b/uui-core/src/data/processing/views/tree/hooks/common/index.ts index cc09242d12..ebdf350a9f 100644 --- a/uui-core/src/data/processing/views/tree/hooks/common/index.ts +++ b/uui-core/src/data/processing/views/tree/hooks/common/index.ts @@ -6,4 +6,4 @@ export * from './useSelectedOnlyTree'; export * from './useSearchTree'; export * from './useSortTree'; export * from './useFilterTree'; -export * from './useActualItemsMap'; +export * from './useActualItemsStorage'; diff --git a/uui-core/src/data/processing/views/tree/hooks/common/useActualItemsMap.ts b/uui-core/src/data/processing/views/tree/hooks/common/useActualItemsMap.ts deleted file mode 100644 index 71d15e1210..0000000000 --- a/uui-core/src/data/processing/views/tree/hooks/common/useActualItemsMap.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { useMemo } from 'react'; -import { ItemsMap } from '../../ItemsMap'; -import { TreeState } from '../../treeState'; - -interface UseActualItemsMapProps { - tree: TreeState; - itemsMap: ItemsMap; -} - -export function useActualItemsMap({ - tree, itemsMap, -}: UseActualItemsMapProps) { - return useMemo(() => { - // if clear cache was executed, itemsMap should not be rewritten. - if (!itemsMap.size) { - return tree; - } - - return tree.updateItemsMap(itemsMap); - }, [tree, itemsMap]); -} diff --git a/uui-core/src/data/processing/views/tree/hooks/common/useActualItemsStorage.ts b/uui-core/src/data/processing/views/tree/hooks/common/useActualItemsStorage.ts new file mode 100644 index 0000000000..60edb56344 --- /dev/null +++ b/uui-core/src/data/processing/views/tree/hooks/common/useActualItemsStorage.ts @@ -0,0 +1,24 @@ +import { useMemo } from 'react'; +import { ItemsMap } from '../../ItemsMap'; +import { TreeState } from '../../treeState'; +import { ItemsStorage } from '../../ItemsStorage'; + +interface UseActualItemsStorageProps { + tree: TreeState; + itemsMap: ItemsMap; + setItems: ItemsStorage['setItems']; +} + +export function useActualItemsStorage({ + tree, itemsMap, setItems, +}: UseActualItemsStorageProps) { + return useMemo(() => { + const updatedTree = tree.updateSetItems(setItems); + // if clear cache was executed, itemsMap should not be rewritten. + if (!itemsMap.size) { + return updatedTree; + } + + return updatedTree.updateItemsMap(itemsMap); + }, [tree, itemsMap, setItems]); +} diff --git a/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/__tests__/useAsyncTree.test.ts b/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/__tests__/useAsyncTree.test.ts index c4f93b5a12..1e4b684b82 100644 --- a/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/__tests__/useAsyncTree.test.ts +++ b/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/__tests__/useAsyncTree.test.ts @@ -102,12 +102,17 @@ describe('useAsyncTree', () => { { initialProps: {} }, ); - const tree = hookResult.result.current; + let tree = hookResult.result.current; + expect(tree.isLoading).toBeTruthy(); + + await waitFor(() => { + tree = hookResult.result.current; + expect(tree.isFetching).toBeFalsy(); + }); expect(tree).toEqual(expect.objectContaining({ dataSourceState, setDataSourceState, - totalCount: 0, getId, getParentId, rowOptions, @@ -193,7 +198,7 @@ describe('useAsyncTree', () => { }); it('should use outer itemsStatusMap if passed to props', async () => { - const itemsStatusMap = newMap({ getId }); + const itemsStatusMap = newMap({}); itemsStatusMap.set('GW', FAILED_RECORD); const hookResult = renderHook( diff --git a/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/useAsyncTree.ts b/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/useAsyncTree.ts index 5d0a5cf39c..ce017af68d 100644 --- a/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/useAsyncTree.ts +++ b/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/useAsyncTree.ts @@ -6,7 +6,7 @@ import { usePrevious } from '../../../../../../../hooks/usePrevious'; import { useItemsStorage, useDataSourceStateWithDefaults, useFilterTree, useSortTree, useSearchTree, useSelectedOnlyTree, usePatchTree, - useActualItemsMap, + useActualItemsStorage, } from '../../common'; import { UseTreeResult } from '../../types'; @@ -61,6 +61,11 @@ export function useAsyncTree( const prevIsForceReload = usePrevious(isForceReload); const dataSourceState = useDataSourceStateWithDefaults({ dataSourceState: props.dataSourceState }); + + useEffect(() => { + setIncommingTree(baseTree); + }, [baseTree]); + const { tree: treeWithData, itemsStatusCollector, isLoaded: isTreeLoaded, isLoading, isFetching } = useLoadData({ getId, complexIds, @@ -80,6 +85,8 @@ export function useAsyncTree( itemsStatusMap, }, [...deps, isForceReload, incommingTree]); + const actualTree = useActualItemsStorage({ tree: treeWithData, itemsMap, setItems }); + const prevIsFetching = usePrevious(isFetching); useEffect(() => { @@ -87,7 +94,7 @@ export function useAsyncTree( && prevIsFetching !== isFetching && !isFetching) { setIsForceReload(false); } - }, [treeWithData]); + }, [actualTree]); const reload = useCallback(() => { setIncommingTree(TreeState.blank({ getId, getParentId, complexIds }, itemsMap, setItems)); @@ -96,8 +103,8 @@ export function useAsyncTree( const isTreeLoading = !isTreeLoaded || isLoading || isFetching; const filteredTree = useFilterTree( - { tree: treeWithData, getFilter, dataSourceState, isLoading: isTreeLoading }, - [treeWithData, isTreeLoading], + { tree: actualTree, getFilter, dataSourceState, isLoading: isTreeLoading }, + [actualTree, isTreeLoading], ); const sortTree = useSortTree( @@ -122,9 +129,10 @@ export function useAsyncTree( isLoading: isTreeLoading, }, [searchTree, isTreeLoading]); - const treeWithNewItemsMap = useActualItemsMap({ + const treeWithNewItemsMap = useActualItemsStorage({ tree: treeWithSelectedOnly, itemsMap, + setItems, }); const { tree, applyPatch } = usePatchTree({ diff --git a/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/useLoadData.ts b/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/useLoadData.ts index 1a90d690ad..c065ea9f7a 100644 --- a/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/useLoadData.ts +++ b/uui-core/src/data/processing/views/tree/hooks/strategies/asyncTree/useLoadData.ts @@ -100,7 +100,9 @@ export function useLoadData( !isFetching && !isLoaded && (!showSelectedOnly || (showSelectedOnly && getSelectedAndChecked(dataSourceState, patch).length)) - ) || forceReload; + ) + || forceReload + || depsChanged; useEffect(() => { if (shouldForceReload) { diff --git a/uui-core/src/data/processing/views/tree/hooks/strategies/lazyTree/useLazyTree.ts b/uui-core/src/data/processing/views/tree/hooks/strategies/lazyTree/useLazyTree.ts index e80884a8fe..24f697b686 100644 --- a/uui-core/src/data/processing/views/tree/hooks/strategies/lazyTree/useLazyTree.ts +++ b/uui-core/src/data/processing/views/tree/hooks/strategies/lazyTree/useLazyTree.ts @@ -4,11 +4,10 @@ import { usePrevious } from '../../../../../../../hooks/usePrevious'; import { useFoldingService } from '../../../../dataRows/services'; import { useLoadData } from './useLoadData'; import { UseTreeResult } from '../../types'; -import { useDataSourceStateWithDefaults, useSelectedOnlyTree, useItemsStorage, usePatchTree, useItemsStatusCollector } from '../../common'; +import { useDataSourceStateWithDefaults, useSelectedOnlyTree, useItemsStorage, usePatchTree, useItemsStatusCollector, useActualItemsStorage } from '../../common'; import { TreeState } from '../../../treeState'; import { useLazyFetchingAdvisor } from './useLazyFetchingAdvisor'; import { isSelectedOrCheckedChanged } from '../checked'; -import { useActualItemsMap } from '../../common'; export function useLazyTree( { flattenSearchResults = true, ...restProps }: LazyTreeProps, @@ -96,10 +95,7 @@ export function useLazyTree( showSelectedOnly, }, [...deps]); - const treeWithDataActual = useActualItemsMap({ - tree: treeWithData, - itemsMap, - }); + const treeWithDataActual = useActualItemsStorage({ tree: treeWithData, setItems, itemsMap }); useEffect(() => { if (showSelectedOnly && isSelectedOrCheckedChanged(dataSourceState, prevDataSourceState)) { @@ -171,13 +167,8 @@ export function useLazyTree( isLoading: isLoading || isFetching, }, [treeWithDataActual]); - const treeWithNewItemsMap = useActualItemsMap({ - tree: treeWithSelectedOnly, - itemsMap, - }); - const { tree, applyPatch } = usePatchTree({ - tree: treeWithNewItemsMap, + tree: treeWithSelectedOnly, patch: showSelectedOnly ? null : patch, isDeleted, getNewItemPosition, diff --git a/uui-core/src/data/processing/views/tree/hooks/strategies/syncTree/useSyncTree.ts b/uui-core/src/data/processing/views/tree/hooks/strategies/syncTree/useSyncTree.ts index a618be773a..4748a93c95 100644 --- a/uui-core/src/data/processing/views/tree/hooks/strategies/syncTree/useSyncTree.ts +++ b/uui-core/src/data/processing/views/tree/hooks/strategies/syncTree/useSyncTree.ts @@ -45,7 +45,7 @@ export function useSyncTree( const fullTree = useCreateTree( { items, itemsMap, setItems, getId, getParentId, complexIds }, - [...deps, items, itemsMap, triggerValue], + [...deps, items, itemsMap, setItems, triggerValue], ); const dataSourceState = useDataSourceStateWithDefaults({ dataSourceState: props.dataSourceState }); diff --git a/uui-core/src/data/processing/views/tree/treeState/TreeState.ts b/uui-core/src/data/processing/views/tree/treeState/TreeState.ts index 6ac71300a4..daead9bddd 100644 --- a/uui-core/src/data/processing/views/tree/treeState/TreeState.ts +++ b/uui-core/src/data/processing/views/tree/treeState/TreeState.ts @@ -294,6 +294,13 @@ export class TreeState { ); } + public updateSetItems(setItems: ItemsStorage['setItems']) { + if (this._setItems !== setItems) { + this._setItems = setItems; + } + return this; + } + private getTreeStructure(treeStructureId: TreeStructureId = 'full') { return (treeStructureId ?? 'full') === 'full' ? this._fullTree : this._visibleTree; }