fix(ui/browse): Fix bug where browse would not paginate when leaving a nested container (#14483)

This commit is contained in:
Andrew Sikowitz 2025-09-15 13:41:41 -07:00 committed by GitHub
parent f38c25dabb
commit 29f717b7d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 50 deletions

View File

@ -1,4 +1,5 @@
import { FolderOutlined } from '@ant-design/icons';
import { Loader } from '@components';
import { Typography } from 'antd';
import React from 'react';
import styled from 'styled-components';
@ -71,7 +72,7 @@ const BrowseNode = () => {
trackSelectNodeEvent(isNowSelected ? 'select' : 'deselect', 'browse');
};
const { error, groups, loaded, observable, path, retry } = useBrowsePagination({
const { error, groups, loading, loaded, observable, path, retry } = useBrowsePagination({
skip: !isOpen || !browseResultGroup.hasSubGroups,
});
@ -118,6 +119,7 @@ const BrowseNode = () => {
<BrowseNode />
</BrowseProvider>
))}
{loading && <Loader size="sm" />}
{error && <SidebarLoadingError onClickRetry={retry} />}
{observable}
</ExpandableNode.Body>

View File

@ -1,3 +1,4 @@
import { Loader } from '@components';
import { Typography } from 'antd';
import React from 'react';
import styled from 'styled-components';
@ -82,7 +83,7 @@ const PlatformNode = ({ iconSize = 20, hasOnlyOnePlatform = false, toggleCollaps
trackSelectNodeEvent(isNowPlatformOnlySelected ? 'select' : 'deselect', 'platform');
};
const { error, groups, loaded, observable, path, retry } = useBrowsePagination({ skip: !isOpen });
const { error, groups, loading, loaded, observable, path, retry } = useBrowsePagination({ skip: !isOpen });
const color = REDESIGN_COLORS.TEXT_HEADING;
@ -169,6 +170,7 @@ const PlatformNode = ({ iconSize = 20, hasOnlyOnePlatform = false, toggleCollaps
<BrowseNode />
</BrowseProvider>
))}
{loading && <Loader size="sm" />}
{error && <SidebarLoadingError onClickRetry={retry} />}
{observable}
</ExpandableNode.Body>

View File

@ -1,11 +1,11 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { useBrowsePath, useEntityType } from '@app/searchV2/sidebar/BrowseContext';
import { BROWSE_LOAD_MORE_MARGIN, BROWSE_PAGE_SIZE } from '@app/searchV2/sidebar/constants';
import { useSidebarFilters } from '@app/searchV2/sidebar/useSidebarFilters';
import useIntersect from '@app/shared/useIntersect';
import { GetBrowseResultsV2Query, useGetBrowseResultsV2LazyQuery } from '@graphql/browseV2.generated';
import { GetBrowseResultsV2Query, useGetBrowseResultsV2Query } from '@graphql/browseV2.generated';
type Props = {
skip: boolean;
@ -33,62 +33,49 @@ const useBrowsePagination = ({ skip }: Props) => {
const total = latestData?.browseV2?.total ?? -1;
const done = !!latestData && groups.length >= total;
const [getBrowseResultsV2, { data, error, refetch }] = useGetBrowseResultsV2LazyQuery({
const [start, setStart] = useState(0);
const { loading, error, refetch } = useGetBrowseResultsV2Query({
skip,
fetchPolicy: 'cache-first',
variables: {
input: {
type,
path,
start,
count: BROWSE_PAGE_SIZE,
orFilters: sidebarFilters.orFilters,
viewUrn: sidebarFilters.viewUrn,
query: sidebarFilters.query,
},
},
onCompleted: (data) => {
const newStart = data?.browseV2?.start ?? -1;
if (newStart === 0) initializing.current = false;
if (initializing.current || !data || newStart < 0) return;
setStartToBrowseMap((previousMap) => {
const newMap: typeof previousMap = { [newStart]: data };
Object.keys(previousMap)
.map(Number)
.forEach((previousStart) => {
if (previousStart < newStart) newMap[previousStart] = previousMap[previousStart];
});
return newMap;
});
},
});
const retry = () => {
if (refetch) refetch();
};
const getBrowseResultsV2WithDeps = useCallback(
(start: number) => {
if (skip) return;
getBrowseResultsV2({
variables: {
input: {
type,
path,
start,
count: BROWSE_PAGE_SIZE,
orFilters: sidebarFilters.orFilters,
viewUrn: sidebarFilters.viewUrn,
query: sidebarFilters.query,
},
},
});
},
[getBrowseResultsV2, path, sidebarFilters.orFilters, sidebarFilters.query, sidebarFilters.viewUrn, skip, type],
);
useEffect(() => {
initializing.current = true;
getBrowseResultsV2WithDeps(0);
}, [getBrowseResultsV2WithDeps]);
useEffect(() => {
const newStart = data?.browseV2?.start ?? -1;
if (newStart === 0) initializing.current = false;
if (initializing.current || !data || newStart < 0) return;
setStartToBrowseMap((previousMap) => {
const newMap: typeof previousMap = { [newStart]: data };
Object.keys(previousMap)
.map(Number)
.forEach((previousStart) => {
if (previousStart < newStart) newMap[previousStart] = previousMap[previousStart];
});
return newMap;
});
}, [data]);
const advancePage = useCallback(() => {
const newStart = latestStart + BROWSE_PAGE_SIZE;
if (initializing.current || error || done || latestStart < 0 || total <= 0 || newStart >= total) return;
getBrowseResultsV2WithDeps(newStart);
}, [done, error, getBrowseResultsV2WithDeps, latestStart, total]);
setStart(newStart);
}, [done, error, latestStart, total]);
const { observableRef } = useIntersect({
skip,
@ -97,6 +84,7 @@ const useBrowsePagination = ({ skip }: Props) => {
});
return {
loading: start > 0 && loading, // Don't display loading indicator for first page
loaded: !!latestData || !!error,
error,
groups,