function useInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): UseInfiniteQueryReturnType<TData, TError>;Defined in: vue-query/src/useInfiniteQuery.ts:117
The options for useInfiniteQuery are identical to useQuery, with the addition of initialPageParam, getNextPageParam, getPreviousPageParam, and maxPages.
This overload is selected when initialData is set, so the resulting data is never undefined.
enabled tracks reactive dependencies automatically as a ref, a plain value, or a reactive getter (() => ...). queryKey reacts through a ref for the array itself, or refs and reactive getters as individual entries — the array itself can't be a bare getter.
TQueryFnData
TError = Error
TData = InfiniteData<TQueryFnData, unknown>
TQueryKey extends readonly unknown[] = readonly unknown[]
TPageParam = unknown
MaybeRefOrGetter<DefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>>
The DefinedInitialDataInfiniteOptions to use — everything you can pass to useInfiniteQuery, with initialData set.
Use this to use a custom QueryClient. Otherwise, the one provided by VueQueryPlugin will be used.
UseInfiniteQueryReturnType<TData, TError>
The same properties as useQuery, with the addition of fetchNextPage, fetchPreviousPage, hasNextPage, hasPreviousPage, isFetchingNextPage, and isFetchingPreviousPage. data.value.pages and data.value.pageParams are also added, as long as a select doesn't change TData away from its default InfiniteData<TQueryFnData> shape.
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.
<script setup lang="ts">
import { useInfiniteQuery } from '@tanstack/vue-query'
// `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: [] },
})
</script>
<template>
<span v-if="isError">Error: {{ error.message }}</span>
<ul>
<template v-for="page in data.pages" :key="page.nextId">
<li v-for="project in page.projects" :key="project.id">{{ project.name }}</li>
</template>
</ul>
</template>function useInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): UseInfiniteQueryReturnType<TData, TError>;Defined in: vue-query/src/useInfiniteQuery.ts:251
The options for useInfiniteQuery are identical to useQuery, with the addition of initialPageParam, getNextPageParam, getPreviousPageParam, and maxPages.
enabled tracks reactive dependencies automatically as a ref, a plain value, or a reactive getter (() => ...). queryKey reacts through a ref for the array itself, or refs and reactive getters as individual entries — the array itself can't be a bare getter.
TQueryFnData
TError = Error
TData = InfiniteData<TQueryFnData, unknown>
TQueryKey extends readonly unknown[] = readonly unknown[]
TPageParam = unknown
MaybeRefOrGetter<UndefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>>
The UndefinedInitialDataInfiniteOptions to use — everything you can pass to useInfiniteQuery.
Use this to use a custom QueryClient. Otherwise, the one provided by VueQueryPlugin will be used.
UseInfiniteQueryReturnType<TData, TError>
The same properties as useQuery, with the addition of fetchNextPage, fetchPreviousPage, hasNextPage, hasPreviousPage, isFetchingNextPage, and isFetchingPreviousPage. data.value.pages and data.value.pageParams are also added, as long as a select doesn't change TData away from its default InfiniteData<TQueryFnData> shape.
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.
Fetching the next page from a "Load More" button click:
<script setup lang="ts">
import { useInfiniteQuery } from '@tanstack/vue-query'
const {
data,
isPending,
isError,
error,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
} = useInfiniteQuery({
queryKey: ['projects'],
queryFn: ({ pageParam }) => fetchProjects(pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
</script>
<template>
<span v-if="isPending">Loading...</span>
<span v-else-if="isError">Error: {{ error.message }}</span>
<template v-else>
<ul>
<template v-for="page in data.pages" :key="page.nextId">
<li v-for="project in page.projects" :key="project.id">{{ project.name }}</li>
</template>
</ul>
<button @click="fetchNextPage()" :disabled="!hasNextPage || isFetching">
{{ isFetchingNextPage ? 'Loading more...' : hasNextPage ? 'Load More' : 'Nothing more to load' }}
</button>
</template>
</template>Fetching the next page automatically as the user scrolls, using an IntersectionObserver on a sentinel element after the list:
<script setup lang="ts">
import { onUnmounted, ref, watch } from 'vue'
import { useInfiniteQuery } from '@tanstack/vue-query'
const {
data,
isPending,
isError,
error,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
} = useInfiniteQuery({
queryKey: ['projects'],
queryFn: ({ pageParam }) => fetchProjects(pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
const sentinel = ref<HTMLElement>()
let observer: IntersectionObserver | undefined
watch(sentinel, (el) => {
observer?.disconnect()
if (el == null) return
observer = new IntersectionObserver(([entry]) => {
if (entry?.isIntersecting && hasNextPage.value && !isFetching.value) {
fetchNextPage()
}
})
observer.observe(el)
})
onUnmounted(() => observer?.disconnect())
</script>
<template>
<span v-if="isPending">Loading...</span>
<span v-else-if="isError">Error: {{ error.message }}</span>
<template v-else>
<ul>
<template v-for="page in data.pages" :key="page.nextId">
<li v-for="project in page.projects" :key="project.id">{{ project.name }}</li>
</template>
</ul>
<div ref="sentinel">{{ isFetchingNextPage ? 'Loading more...' : '' }}</div>
</template>
</template>function useInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options, queryClient?): UseInfiniteQueryReturnType<TData, TError>;Defined in: vue-query/src/useInfiniteQuery.ts:347
Fallback overload for options whose initialData presence isn't statically known — for example, a ref/reactive object built up conditionally, rather than a plain object literal. Prefer one of the other overloads when possible, since they infer whether data can be undefined from initialData directly.
enabled tracks reactive dependencies automatically as a ref, a plain value, or a reactive getter (() => ...). queryKey reacts through a ref for the array itself, or refs and reactive getters as individual entries — the array itself can't be a bare getter.
TQueryFnData
TError = Error
TData = InfiniteData<TQueryFnData, unknown>
TQueryKey extends readonly unknown[] = readonly unknown[]
TPageParam = unknown
MaybeRefOrGetter<UseInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>>
A ref, plain value, or reactive getter resolving to the UseInfiniteQueryOptions to use.
Use this to use a custom QueryClient. Otherwise, the one provided by VueQueryPlugin will be used.
UseInfiniteQueryReturnType<TData, TError>
The same properties as useQuery, with the addition of fetchNextPage, fetchPreviousPage, hasNextPage, hasPreviousPage, isFetchingNextPage, and isFetchingPreviousPage.
Passing a whole-options getter so maxPages reacts to a setting stored elsewhere, not just queryKey:
<script setup lang="ts">
import { useInfiniteQuery } from '@tanstack/vue-query'
const props = defineProps<{ projectId: number; maxPages: number }>()
const { data } = useInfiniteQuery(() => ({
queryKey: ['project', props.projectId, 'issues'],
queryFn: ({ pageParam }) => fetchIssues(props.projectId, pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
maxPages: props.maxPages,
}))
</script>
<template>
<template v-for="page in data?.pages" :key="page.nextId">
<li v-for="issue in page.issues" :key="issue.id">{{ issue.title }}</li>
</template>
</template>A query that's disabled, type-safe, until postId is set — pass skipToken as queryFn instead of setting enabled: false. This requires a whole-options getter: queryFn isn't itself reactive, so the getter is what re-evaluates it on every change to props.postId:
<script setup lang="ts">
import { skipToken, useInfiniteQuery } from '@tanstack/vue-query'
const props = defineProps<{ 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(() => {
const postId = props.postId
return {
queryKey: ['post', postId, 'comments'],
queryFn:
postId != null
? ({ pageParam }) => fetchComments(postId, pageParam)
: skipToken,
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
}
})
</script>
<template>
<span v-if="props.postId == null">Select a post</span>
<span v-else-if="isLoading">Loading...</span>
<span v-else-if="isError">Error: {{ error.message }}</span>
<ul v-else>
<template v-for="page in data.pages" :key="page.nextId">
<li v-for="comment in page.comments" :key="comment.id">{{ comment.text }}</li>
</template>
</ul>
</template>