mirror of https://github.com/buster-so/buster.git
added infinite scroll functionality
This commit is contained in:
parent
9a9b5fb674
commit
02ce6d6b3a
|
@ -1,13 +1,9 @@
|
||||||
import type { SearchTextResponse } from '@buster/server-shared/search';
|
import type { SearchTextData, SearchTextResponse } from '@buster/server-shared/search';
|
||||||
import {
|
import { keepPreviousData, type UseQueryOptions, useQuery } from '@tanstack/react-query';
|
||||||
keepPreviousData,
|
|
||||||
type UseQueryOptions,
|
|
||||||
useInfiniteQuery,
|
|
||||||
useQuery,
|
|
||||||
} from '@tanstack/react-query';
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import type { ApiError } from '@/api/errors';
|
import type { ApiError } from '@/api/errors';
|
||||||
import { getSearchResultInfinite, searchQueryKeys } from '@/api/query_keys/search';
|
import { getSearchResultInfinite, searchQueryKeys } from '@/api/query_keys/search';
|
||||||
|
import { useInfiniteScroll } from '@/api/query-helpers';
|
||||||
import { search } from './requests';
|
import { search } from './requests';
|
||||||
|
|
||||||
export const useSearch = <T = SearchTextResponse>(
|
export const useSearch = <T = SearchTextResponse>(
|
||||||
|
@ -31,17 +27,10 @@ export const useSearchInfinite = (
|
||||||
) => {
|
) => {
|
||||||
const [searchQuery, setSearchQuery] = useState<string>('');
|
const [searchQuery, setSearchQuery] = useState<string>('');
|
||||||
|
|
||||||
const queryResult = useInfiniteQuery({
|
const queryResult = useInfiniteScroll<SearchTextData>({
|
||||||
queryKey: ['search', 'results', 'infinite', params] as const,
|
queryKey: ['search', 'results', 'infinite', params] as const,
|
||||||
staleTime: 1000 * 30, // 30 seconds,
|
staleTime: 1000 * 30, // 30 seconds
|
||||||
queryFn: ({ pageParam = 1 }) => search({ query: searchQuery, page: pageParam, ...params }),
|
queryFn: ({ pageParam = 1 }) => search({ query: searchQuery, page: pageParam, ...params }),
|
||||||
getNextPageParam: (lastPage) => {
|
|
||||||
if (!lastPage.pagination.has_more) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return lastPage.pagination.page + 1;
|
|
||||||
},
|
|
||||||
initialPageParam: 1,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return { ...queryResult, setSearchQuery, searchQuery };
|
return { ...queryResult, setSearchQuery, searchQuery };
|
||||||
|
|
|
@ -1,36 +1,19 @@
|
||||||
import { useInfiniteQuery } from '@tanstack/react-query';
|
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute } from '@tanstack/react-router';
|
||||||
import { useEffect, useRef } from 'react';
|
import { useSearchInfinite } from '@/api/buster_rest/search';
|
||||||
import { search, useSearchInfinite } from '@/api/buster_rest/search';
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/app/_app/test-pagination')({
|
export const Route = createFileRoute('/app/_app/test-pagination')({
|
||||||
component: RouteComponent,
|
component: RouteComponent,
|
||||||
});
|
});
|
||||||
|
|
||||||
function RouteComponent() {
|
function RouteComponent() {
|
||||||
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = useSearchInfinite();
|
const {
|
||||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
scrollContainerRef,
|
||||||
|
allResults,
|
||||||
// Combine all pages into a single array of results
|
hasNextPage,
|
||||||
const allResults = data?.pages.flatMap((page) => page.data) ?? [];
|
isFetchingNextPage,
|
||||||
|
isLoading,
|
||||||
useEffect(() => {
|
fetchNextPage,
|
||||||
const container = scrollContainerRef.current;
|
} = useSearchInfinite();
|
||||||
if (!container) return;
|
|
||||||
|
|
||||||
const handleScroll = () => {
|
|
||||||
const { scrollTop, scrollHeight, clientHeight } = container;
|
|
||||||
// Trigger when user is within 100px of the bottom
|
|
||||||
if (scrollHeight - scrollTop - clientHeight < 100) {
|
|
||||||
if (hasNextPage && !isFetchingNextPage) {
|
|
||||||
fetchNextPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
container.addEventListener('scroll', handleScroll);
|
|
||||||
return () => container.removeEventListener('scroll', handleScroll);
|
|
||||||
}, [hasNextPage, isFetchingNextPage, fetchNextPage]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
Loading…
Reference in New Issue