function useInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): DefinedUseInfiniteQueryResult<TData, TError>;Defined in: preact-query/src/useInfiniteQuery.ts:64
The options for useInfiniteQuery are identical to useQuery, with the addition of queryFn, initialPageParam, getNextPageParam, getPreviousPageParam, and maxPages.
This overload is selected when initialData is set.
TQueryFnData
TError = Error
TData = InfiniteData<TQueryFnData, unknown>
TQueryKey extends readonly unknown[] = readonly unknown[]
TPageParam = unknown
DefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>
The DefinedInitialDataInfiniteOptions to use — everything you can pass to useInfiniteQuery, with initialData set.
QueryClient
Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.
DefinedUseInfiniteQueryResult<TData, TError>
The same properties as useQuery, with the addition of data.pages, data.pageParams, fetchNextPage, fetchPreviousPage, hasNextPage, hasPreviousPage, isFetchingNextPage, and isFetchingPreviousPage.
Keep in mind that imperative fetch calls, such as fetchNextPage, may interfere with the default refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user actions, or add conditions like hasNextPage && !isFetching.
infiniteQueryOptions to share these options between useInfiniteQuery and imperative APIs like queryClient.infiniteQuery.
import { useInfiniteQuery } from '@tanstack/preact-query'
function Projects() {
// `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the
// list stays visible alongside the error.
const { data, isError, error } = useInfiniteQuery({
queryKey: ['projects'],
queryFn: ({ pageParam }) => fetchProjects(pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
initialData: { pages: [], pageParams: [] },
})
return (
<div>
{isError ? <span>Error: {error.message}</span> : null}
<ul>
{data.pages.map((page) => page.projects.map((p) => <li key={p.id}>{p.name}</li>))}
</ul>
</div>
)
}function useInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): UseInfiniteQueryResult<TData, TError>;Defined in: preact-query/src/useInfiniteQuery.ts:189
The options for useInfiniteQuery are identical to useQuery, with the addition of queryFn, initialPageParam, getNextPageParam, getPreviousPageParam, and maxPages.
TQueryFnData
TError = Error
TData = InfiniteData<TQueryFnData, unknown>
TQueryKey extends readonly unknown[] = readonly unknown[]
TPageParam = unknown
UndefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>
The UndefinedInitialDataInfiniteOptions to use — everything you can pass to useInfiniteQuery.
QueryClient
Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.
UseInfiniteQueryResult<TData, TError>
The same properties as useQuery, with the addition of data.pages, data.pageParams, fetchNextPage, fetchPreviousPage, hasNextPage, hasPreviousPage, isFetchingNextPage, and isFetchingPreviousPage.
Keep in mind that imperative fetch calls, such as fetchNextPage, may interfere with the default refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user actions, or add conditions like hasNextPage && !isFetching.
infiniteQueryOptions to share these options between useInfiniteQuery and imperative APIs like queryClient.infiniteQuery.
Fetching the next page from a "Load More" button click:
import { useInfiniteQuery } from '@tanstack/preact-query'
function Projects() {
const { data, isPending, isError, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } =
useInfiniteQuery({
queryKey: ['projects'],
queryFn: ({ pageParam }) => fetchProjects(pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
if (isPending) return 'Loading...'
if (isError) return <span>Error: {error.message}</span>
return (
<>
<ul>
{data.pages.map((page) =>
page.projects.map((project) => <li key={project.id}>{project.name}</li>),
)}
</ul>
<button
onClick={() => fetchNextPage()}
disabled={!hasNextPage || isFetching}
>
{isFetchingNextPage
? 'Loading more...'
: hasNextPage
? 'Load More'
: 'Nothing more to load'}
</button>
</>
)
}Fetching the next page automatically as the user scrolls, using an IntersectionObserver on a sentinel element after the list:
import { useInfiniteQuery } from '@tanstack/preact-query'
import { useEffect, useRef } from 'preact/hooks'
function Projects() {
const {
data,
isPending,
isError,
error,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
} = useInfiniteQuery({
queryKey: ['projects'],
queryFn: ({ pageParam }) => fetchProjects(pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
const sentinelRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const sentinel = sentinelRef.current
if (sentinel == null || !hasNextPage || isFetching) return
const observer = new IntersectionObserver(([entry]) => {
if (entry?.isIntersecting) fetchNextPage()
})
observer.observe(sentinel)
return () => observer.disconnect()
}, [hasNextPage, isFetching, fetchNextPage])
if (isPending) return 'Loading...'
if (isError) return <span>Error: {error.message}</span>
return (
<>
<ul>
{data.pages.map((page) =>
page.projects.map((project) => <li key={project.id}>{project.name}</li>),
)}
</ul>
<div ref={sentinelRef}>{isFetchingNextPage ? 'Loading more...' : null}</div>
</>
)
}function useInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): UseInfiniteQueryResult<TData, TError>;Defined in: preact-query/src/useInfiniteQuery.ts:390
The options for useInfiniteQuery are identical to useQuery, with the addition of queryFn, initialPageParam, getNextPageParam, getPreviousPageParam, and maxPages.
TQueryFnData
TError = Error
TData = InfiniteData<TQueryFnData, unknown>
TQueryKey extends readonly unknown[] = readonly unknown[]
TPageParam = unknown
UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>
The UseInfiniteQueryOptions to use — everything you can pass to useInfiniteQuery.
QueryClient
Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used.
UseInfiniteQueryResult<TData, TError>
The same properties as useQuery, with the addition of data.pages, data.pageParams, fetchNextPage, fetchPreviousPage, hasNextPage, hasPreviousPage, isFetchingNextPage, and isFetchingPreviousPage.
Keep in mind that imperative fetch calls, such as fetchNextPage, may interfere with the default refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user actions, or add conditions like hasNextPage && !isFetching.
infiniteQueryOptions to share these options between useInfiniteQuery and imperative APIs like queryClient.infiniteQuery.
Fetching the next page from a "Load More" button click:
import { useInfiniteQuery } from '@tanstack/preact-query'
function Projects() {
const { data, isPending, isError, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } =
useInfiniteQuery({
queryKey: ['projects'],
queryFn: ({ pageParam }) => fetchProjects(pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
if (isPending) return 'Loading...'
if (isError) return <span>Error: {error.message}</span>
return (
<>
<ul>
{data.pages.map((page) =>
page.projects.map((project) => <li key={project.id}>{project.name}</li>),
)}
</ul>
<button
onClick={() => fetchNextPage()}
disabled={!hasNextPage || isFetching}
>
{isFetchingNextPage
? 'Loading more...'
: hasNextPage
? 'Load More'
: 'Nothing more to load'}
</button>
</>
)
}Fetching the next page automatically as the user scrolls, using an IntersectionObserver on a sentinel element after the list:
import { useInfiniteQuery } from '@tanstack/preact-query'
import { useEffect, useRef } from 'preact/hooks'
function Projects() {
const {
data,
isPending,
isError,
error,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
} = useInfiniteQuery({
queryKey: ['projects'],
queryFn: ({ pageParam }) => fetchProjects(pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
const sentinelRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const sentinel = sentinelRef.current
if (sentinel == null || !hasNextPage || isFetching) return
const observer = new IntersectionObserver(([entry]) => {
if (entry?.isIntersecting) fetchNextPage()
})
observer.observe(sentinel)
return () => observer.disconnect()
}, [hasNextPage, isFetching, fetchNextPage])
if (isPending) return 'Loading...'
if (isError) return <span>Error: {error.message}</span>
return (
<>
<ul>
{data.pages.map((page) =>
page.projects.map((project) => <li key={project.id}>{project.name}</li>),
)}
</ul>
<div ref={sentinelRef}>{isFetchingNextPage ? 'Loading more...' : null}</div>
</>
)
}Warming the cache on hover, so <Comments> has data as soon as it's clicked. Requires an infiniteQueryOptions factory, so the hook and the imperative call share the same cache entry:
import {
infiniteQueryOptions,
noop,
useInfiniteQuery,
useQueryClient,
} from '@tanstack/preact-query'
const commentsOptions = (postId: string) =>
infiniteQueryOptions({
queryKey: ['post', postId, 'comments'],
queryFn: ({ pageParam }) => fetchComments(postId, pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
function Comments({ postId }: { postId: string }) {
const { data, isPending, isError, error } = useInfiniteQuery(commentsOptions(postId))
if (isPending) return 'Loading...'
if (isError) return <span>Error: {error.message}</span>
return (
<ul>
{data.pages.map((page) => page.comments.map((c) => <li key={c.id}>{c.text}</li>))}
</ul>
)
}
function PostLink({ postId, title }: { postId: string; title: string }) {
const queryClient = useQueryClient()
return (
<a
href={`/posts/${postId}`}
onMouseEnter={() => queryClient.infiniteQuery(commentsOptions(postId)).catch(noop)}
>
{title}
</a>
)
}A query that's disabled, type safe, until postId is set — pass skipToken as queryFn instead of setting enabled: false:
import { skipToken, useInfiniteQuery } from '@tanstack/preact-query'
function Comments({ postId }: { postId: string | undefined }) {
// Use `isLoading`, not `isPending`, so the loading state doesn't show while the query is disabled.
const { data, isLoading, isError, error } = useInfiniteQuery({
queryKey: ['post', postId, 'comments'],
queryFn:
postId != null
? ({ pageParam }) => fetchComments(postId, pageParam)
: skipToken,
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
if (postId == null) return 'Select a post'
if (isLoading) return 'Loading...'
if (isError) return <span>Error: {error.message}</span>
return (
<ul>
{data?.pages.map((page) => page.comments.map((c) => <li key={c.id}>{c.text}</li>))}
</ul>
)
}