Generic custom useInfiniteQuery hook #9793
Replies: 1 comment
-
|
Excellent question — this is a very common pitfall when writing generic custom hooks around Let’s break it down carefully 👇 🧠 The Core IssueWhen you re-expose a generic React Query hook like That’s what’s happening in your case. React Query’s internal ✅ Correct Typing FixYou just need to make your generic parameters mirror React Query’s definitions exactly, keeping the import {
useInfiniteQuery,
type UseInfiniteQueryOptions,
type UseInfiniteQueryResult,
type QueryKey,
} from "@tanstack/react-query";
import { useEffect } from "react";
import { useInView } from "react-intersection-observer";
export function useInfiniteQueryWithScrollPagination<
TQueryFnData,
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = unknown
>(
queryOptions: UseInfiniteQueryOptions<
TQueryFnData,
TError,
TData,
TQueryKey,
TPageParam
>
): UseInfiniteQueryResult<TData, TError> & { paginatorRef: (node?: Element | null) => void } {
const { ref, inView } = useInView();
const infiniteQuery = useInfiniteQuery(queryOptions);
useEffect(() => {
if (inView && infiniteQuery.hasNextPage && !infiniteQuery.isFetchingNextPage) {
void infiniteQuery.fetchNextPage();
}
}, [inView, infiniteQuery.hasNextPage, infiniteQuery.isFetchingNextPage, infiniteQuery.fetchNextPage]);
return { ...infiniteQuery, paginatorRef: ref };
}🧩 Explanation of the Fix
💡 Optional ImprovementIf you often use this pattern, you can simplify user-facing ergonomics by letting TS infer types directly from the options: export function useInfiniteQueryWithScrollPagination<
TQueryFnData,
TError,
TData,
TQueryKey extends QueryKey,
TPageParam
>(
options: UseInfiniteQueryOptions<
TQueryFnData,
TError,
TData,
TQueryKey,
TPageParam
>
) {
const { ref, inView } = useInView();
const query = useInfiniteQuery(options);
useEffect(() => {
if (inView && query.hasNextPage && !query.isFetchingNextPage) {
void query.fetchNextPage();
}
}, [inView, query.hasNextPage, query.isFetchingNextPage, query.fetchNextPage]);
return { ...query, paginatorRef: ref };
}Now TypeScript will infer everything cleanly when you pass |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I know Dominik generally recommends to not have custom queries that accept all options, but in this case. the custom hook should accept all options as it is quite generic.
So i this the correct way to type it?
When the generics are not passed,
pageParamis infered as unknown, also when using options created infiniteQueryOptions(),i get
Beta Was this translation helpful? Give feedback.
All reactions