Skip to content

Instantly share code, notes, and snippets.

@isocroft
Last active November 5, 2025 14:48
Show Gist options
  • Select an option

  • Save isocroft/762fe55cd2c453d221205a099bd888e1 to your computer and use it in GitHub Desktop.

Select an option

Save isocroft/762fe55cd2c453d221205a099bd888e1 to your computer and use it in GitHub Desktop.
React Infinite Scroll Hook using react-query and react-busser
import { useEffect, useRef } from "react";
import { useIsDOMElementVisibleOnScreen } from "react-busser";
import type { InfiniteQueryResult, InfiniteQueryKey, InfiniteQueryFunction, InfiniteQueryOptions } from "react-query";
import { useInfiniteQuery } from "react-query";
export type InfiniteScrollQueryOptions<TK, TR, TMV, TE> = {
queryKey: InfiniteQueryKey<TK>;
queryFn?: InfiniteQueryFunction<TR, TK, TMV>;
config?: InfiniteQueryOptions<TR, TMV, TE>;
};
export function useInfiniteScrollForQueries <K, D, T, E = Error>(queryOptions: InfiniteScrollQueryOptions<K, D, T, E>, scrollOptions = { rootMargin: "0px", threshold: 1 }) {
const { fetchNextPage, hasNextPage, ...query } = useInfiniteQuery(queryOptions);
const [ isIntersecting, domElementRef ] = useIsDOMElementVisibleOnScreen(scrollOptions);
/* @HINT: Use the latest ref pattern */
const fetcher = useRef(fetchNextPage);
useEffect(() => {
fetcher.current = fetchNextPage;
});
useEffect(() => {
if (isIntersecting && hasNextPage) {
fetcher.current();
}
}, [isIntersecting, hasNextPage]);
const queryResult = { ...query, hasNextPage, fetchNextPage } as InfiniteQueryResult<D, T, E>;
return [queryResult, domElementRef] as const;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment