refactor infinite loader to use query state

This commit is contained in:
jeffvli
2025-10-10 18:38:39 -07:00
parent 0b11aff395
commit 430acef92e
@@ -1,6 +1,11 @@
import { useQueryClient, useSuspenseQuery, UseSuspenseQueryOptions } from '@tanstack/react-query'; import {
useQuery,
useQueryClient,
useSuspenseQuery,
UseSuspenseQueryOptions,
} from '@tanstack/react-query';
import throttle from 'lodash/throttle'; import throttle from 'lodash/throttle';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef } from 'react';
import { queryKeys } from '/@/renderer/api/query-keys'; import { queryKeys } from '/@/renderer/api/query-keys';
import { eventEmitter } from '/@/renderer/events/event-emitter'; import { eventEmitter } from '/@/renderer/events/event-emitter';
@@ -42,7 +47,24 @@ export const useItemListInfiniteLoader = ({
const pagesLoaded = useRef<Record<string, boolean>>({}); const pagesLoaded = useRef<Record<string, boolean>>({});
const [data, setData] = useState<unknown[]>(getInitialData(totalItemCount)); // Reset the loaded pages when the query changes
useEffect(() => {
pagesLoaded.current = {};
}, [query]);
const dataQueryKey = useMemo(
() => [serverId, 'item-list-infinite-loader', query],
[serverId, query],
);
const { data } = useQuery<unknown[]>({
enabled: false,
initialData: getInitialData(totalItemCount),
queryFn: () => {
return getInitialData(totalItemCount);
},
queryKey: dataQueryKey,
});
const onRangeChanged = useMemo(() => { const onRangeChanged = useMemo(() => {
return throttle(async (range: { endIndex: number; startIndex: number }) => { return throttle(async (range: { endIndex: number; startIndex: number }) => {
@@ -78,13 +100,13 @@ export const useItemListInfiniteLoader = ({
staleTime: 1000 * 15, staleTime: 1000 * 15,
}); });
setData((oldData: any) => { queryClient.setQueryData(dataQueryKey, (oldData: unknown[]) => {
return [...oldData.slice(0, startIndex), ...result, ...oldData.slice(endIndex)]; return [...oldData.slice(0, startIndex), ...result, ...oldData.slice(endIndex)];
}); });
pagesLoaded.current[pageNumber] = true; pagesLoaded.current[pageNumber] = true;
}, 500); }, 500);
}, [itemsPerPage, queryClient, serverId, listQueryFn, query]); }, [itemsPerPage, query, queryClient, serverId, dataQueryKey, listQueryFn]);
const refresh = useCallback( const refresh = useCallback(
async (force?: boolean) => { async (force?: boolean) => {
@@ -92,7 +114,7 @@ export const useItemListInfiniteLoader = ({
pagesLoaded.current = {}; pagesLoaded.current = {};
if (force) { if (force) {
setData(getInitialData(totalItemCount)); await queryClient.setQueryData(dataQueryKey, getInitialData(totalItemCount));
} }
await onRangeChanged({ await onRangeChanged({
@@ -100,27 +122,30 @@ export const useItemListInfiniteLoader = ({
startIndex: currentPageRef.current * itemsPerPage, startIndex: currentPageRef.current * itemsPerPage,
}); });
}, },
[itemsPerPage, onRangeChanged, queryClient, totalItemCount], [itemsPerPage, onRangeChanged, queryClient, totalItemCount, dataQueryKey],
); );
const updateItems = useCallback((indexes: number[], value: object) => { const updateItems = useCallback(
setData((prev: any[]) => { (indexes: number[], value: object) => {
return prev.map((item: any, index) => { queryClient.setQueryData(dataQueryKey, (prev: unknown[]) => {
if (!item) { return prev.map((item: any, index) => {
return item; if (!item) {
} return item;
}
if (!indexes.includes(index)) { if (!indexes.includes(index)) {
return item; return item;
} }
return { return {
...item, ...item,
...value, ...value,
}; };
});
}); });
}); },
}, []); [queryClient, dataQueryKey],
);
useEffect(() => { useEffect(() => {
const handleRefresh = (payload: { key: string }) => { const handleRefresh = (payload: { key: string }) => {