snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
This commit is contained in:
@@ -0,0 +1,350 @@
|
||||
---
|
||||
id: injectInfiniteQuery
|
||||
title: injectInfiniteQuery
|
||||
---
|
||||
|
||||
## Call Signature
|
||||
|
||||
```ts
|
||||
function injectInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(injectInfiniteQueryFn, options?): DefinedCreateInfiniteQueryResult<TData, TError>;
|
||||
```
|
||||
|
||||
Defined in: [packages/angular-query-experimental/src/inject-infinite-query.ts:83](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L83)
|
||||
|
||||
The options for `injectInfiniteQuery` are identical to `injectQuery`, with the addition of
|
||||
`initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. Infinite queries can
|
||||
additively "load more" data onto an existing set of data, or "infinite scroll".
|
||||
|
||||
This overload is selected when `initialData` is set on the options returned by `injectInfiniteQueryFn`,
|
||||
so the resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`).
|
||||
|
||||
### Type Parameters
|
||||
|
||||
#### TQueryFnData
|
||||
|
||||
`TQueryFnData`
|
||||
|
||||
#### TError
|
||||
|
||||
`TError` = `Error`
|
||||
|
||||
#### TData
|
||||
|
||||
`TData` = [`InfiniteData`](../interfaces/InfiniteData.md)\<`TQueryFnData`, `unknown`\>
|
||||
|
||||
#### TQueryKey
|
||||
|
||||
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
|
||||
|
||||
#### TPageParam
|
||||
|
||||
`TPageParam` = `unknown`
|
||||
|
||||
### Parameters
|
||||
|
||||
#### injectInfiniteQueryFn
|
||||
|
||||
() => [`DefinedInitialDataInfiniteOptions`](../type-aliases/DefinedInitialDataInfiniteOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>
|
||||
|
||||
A function returning the [DefinedInitialDataInfiniteOptions](../type-aliases/DefinedInitialDataInfiniteOptions.md) to use —
|
||||
everything you can pass to `injectInfiniteQuery`, with `initialData` set. Similar to `computed` from
|
||||
Angular, this function runs in the reactive context, so signals read inside it drive the query.
|
||||
|
||||
#### options?
|
||||
|
||||
[`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md)
|
||||
|
||||
Additional configuration.
|
||||
|
||||
### Returns
|
||||
|
||||
[`DefinedCreateInfiniteQueryResult`](../type-aliases/DefinedCreateInfiniteQueryResult.md)\<`TData`, `TError`\>
|
||||
|
||||
The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`,
|
||||
`hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and
|
||||
`data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default
|
||||
`InfiniteData<TQueryFnData>` shape.
|
||||
|
||||
### Remarks
|
||||
|
||||
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()`.
|
||||
|
||||
### See
|
||||
|
||||
[infiniteQueryOptions](infiniteQueryOptions.md) to share these options between `injectInfiniteQuery` and imperative APIs
|
||||
like `queryClient.fetchInfiniteQuery`.
|
||||
|
||||
### Example
|
||||
|
||||
```angular-ts
|
||||
@Component({
|
||||
selector: 'projects',
|
||||
template: `
|
||||
<!-- `projectsQuery.data()` is never `undefined`, thanks to `initialData` — even if a
|
||||
refetch fails, so the list stays visible alongside the error. -->
|
||||
<ul>
|
||||
@for (page of projectsQuery.data().pages; track $index) {
|
||||
@for (project of page.projects; track project.id) {
|
||||
<li>{{ project.name }}</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
`,
|
||||
})
|
||||
export class Projects {
|
||||
readonly projectsQuery = injectInfiniteQuery(() => ({
|
||||
queryKey: ['projects'],
|
||||
queryFn: ({ pageParam }) => fetchProjects(pageParam),
|
||||
initialPageParam: 0,
|
||||
getNextPageParam: (lastPage) => lastPage.nextId,
|
||||
initialData: { pages: [], pageParams: [] },
|
||||
}))
|
||||
}
|
||||
```
|
||||
|
||||
## Call Signature
|
||||
|
||||
```ts
|
||||
function injectInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(injectInfiniteQueryFn, options?): CreateInfiniteQueryResult<TData, TError>;
|
||||
```
|
||||
|
||||
Defined in: [packages/angular-query-experimental/src/inject-infinite-query.ts:239](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L239)
|
||||
|
||||
Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a
|
||||
unique key. Infinite queries can additively "load more" data onto an existing set of data, or
|
||||
"infinite scroll".
|
||||
|
||||
### Type Parameters
|
||||
|
||||
#### TQueryFnData
|
||||
|
||||
`TQueryFnData`
|
||||
|
||||
#### TError
|
||||
|
||||
`TError` = `Error`
|
||||
|
||||
#### TData
|
||||
|
||||
`TData` = [`InfiniteData`](../interfaces/InfiniteData.md)\<`TQueryFnData`, `unknown`\>
|
||||
|
||||
#### TQueryKey
|
||||
|
||||
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
|
||||
|
||||
#### TPageParam
|
||||
|
||||
`TPageParam` = `unknown`
|
||||
|
||||
### Parameters
|
||||
|
||||
#### injectInfiniteQueryFn
|
||||
|
||||
() => [`UndefinedInitialDataInfiniteOptions`](../type-aliases/UndefinedInitialDataInfiniteOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>
|
||||
|
||||
A function returning the [UndefinedInitialDataInfiniteOptions](../type-aliases/UndefinedInitialDataInfiniteOptions.md) to use
|
||||
— everything you can pass to `injectInfiniteQuery`. Similar to `computed` from Angular, this function runs
|
||||
in the reactive context, so signals read inside it drive the query.
|
||||
|
||||
#### options?
|
||||
|
||||
[`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md)
|
||||
|
||||
Additional configuration.
|
||||
|
||||
### Returns
|
||||
|
||||
[`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\>
|
||||
|
||||
The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`,
|
||||
`hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and
|
||||
`data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default
|
||||
`InfiniteData<TQueryFnData>` shape.
|
||||
|
||||
### Remarks
|
||||
|
||||
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()`. This is the only overload that accepts
|
||||
`queryFn: skipToken`, shown below.
|
||||
|
||||
### See
|
||||
|
||||
[infiniteQueryOptions](infiniteQueryOptions.md) to share these options between `injectInfiniteQuery` and imperative APIs
|
||||
like `queryClient.fetchInfiniteQuery`.
|
||||
|
||||
### Examples
|
||||
|
||||
Fetching the next page from a button click:
|
||||
```angular-ts
|
||||
@Component({
|
||||
selector: 'projects-list',
|
||||
template: `
|
||||
<ul>
|
||||
@for (page of projectsQuery.data()?.pages; track $index) {
|
||||
@for (project of page.projects; track project.id) {
|
||||
<li>{{ project.name }}</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
<button
|
||||
[disabled]="!projectsQuery.hasNextPage() || projectsQuery.isFetching()"
|
||||
(click)="projectsQuery.fetchNextPage()"
|
||||
>
|
||||
Load More
|
||||
</button>
|
||||
`,
|
||||
})
|
||||
export class ProjectsList {
|
||||
readonly projectsQuery = injectInfiniteQuery(() => ({
|
||||
queryKey: ['projects'],
|
||||
queryFn: ({ pageParam }) => fetchProjects(pageParam),
|
||||
initialPageParam: 0,
|
||||
getNextPageParam: (lastPage) => lastPage.nextId,
|
||||
}))
|
||||
}
|
||||
```
|
||||
|
||||
Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a sentinel
|
||||
element after the list:
|
||||
```angular-ts
|
||||
@Component({
|
||||
selector: 'projects-list',
|
||||
template: `
|
||||
<ul>
|
||||
@for (page of projectsQuery.data()?.pages; track $index) {
|
||||
@for (project of page.projects; track project.id) {
|
||||
<li>{{ project.name }}</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
<div #sentinel>{{ projectsQuery.isFetchingNextPage() ? 'Loading more...' : '' }}</div>
|
||||
`,
|
||||
})
|
||||
export class ProjectsList {
|
||||
readonly sentinel = viewChild<ElementRef<HTMLElement>>('sentinel')
|
||||
|
||||
readonly projectsQuery = injectInfiniteQuery(() => ({
|
||||
queryKey: ['projects'],
|
||||
queryFn: ({ pageParam }) => fetchProjects(pageParam),
|
||||
initialPageParam: 0,
|
||||
getNextPageParam: (lastPage) => lastPage.nextId,
|
||||
}))
|
||||
|
||||
constructor() {
|
||||
effect((onCleanup) => {
|
||||
const sentinel = this.sentinel()?.nativeElement
|
||||
if (
|
||||
sentinel == null ||
|
||||
!this.projectsQuery.hasNextPage() ||
|
||||
this.projectsQuery.isFetching()
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const observer = new IntersectionObserver(([entry]) => {
|
||||
if (entry?.isIntersecting) this.projectsQuery.fetchNextPage()
|
||||
})
|
||||
observer.observe(sentinel)
|
||||
|
||||
onCleanup(() => observer.disconnect())
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A query that's disabled, type safe, until `postId` is set — pass `skipToken` as `queryFn` instead of
|
||||
setting `enabled: false`:
|
||||
```angular-ts
|
||||
@Component({
|
||||
selector: 'comments',
|
||||
template: `
|
||||
@if (postId() == null) {
|
||||
Select a post
|
||||
} @else if (commentsQuery.isPending()) {
|
||||
Loading...
|
||||
} @else if (commentsQuery.isError()) {
|
||||
<span>Error: {{ commentsQuery.error()?.message }}</span>
|
||||
} @else {
|
||||
<ul>
|
||||
@for (page of commentsQuery.data().pages; track $index) {
|
||||
@for (comment of page.comments; track comment.id) {
|
||||
<li>{{ comment.text }}</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
`,
|
||||
})
|
||||
export class Comments {
|
||||
readonly postId = signal<string | undefined>(undefined)
|
||||
|
||||
readonly commentsQuery = injectInfiniteQuery(() => ({
|
||||
queryKey: ['post', this.postId(), 'comments'],
|
||||
queryFn:
|
||||
this.postId() != null
|
||||
? ({ pageParam }) => fetchComments(this.postId()!, pageParam)
|
||||
: skipToken,
|
||||
initialPageParam: 0,
|
||||
getNextPageParam: (lastPage) => lastPage.nextId,
|
||||
}))
|
||||
}
|
||||
```
|
||||
|
||||
## Call Signature
|
||||
|
||||
```ts
|
||||
function injectInfiniteQuery<TQueryFnData, TError, TData, TQueryKey, TPageParam>(injectInfiniteQueryFn, options?): CreateInfiniteQueryResult<TData, TError>;
|
||||
```
|
||||
|
||||
Defined in: [packages/angular-query-experimental/src/inject-infinite-query.ts:267](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-infinite-query.ts#L267)
|
||||
|
||||
This overload accepts the general [CreateInfiniteQueryOptions](../interfaces/CreateInfiniteQueryOptions.md) shape rather than the
|
||||
`initialData`-aware overloads above, so whether `data` is defined can't be inferred from the call site —
|
||||
useful when wrapping `injectInfiniteQuery` in your own helper function that forwards caller-provided
|
||||
options.
|
||||
|
||||
### Type Parameters
|
||||
|
||||
#### TQueryFnData
|
||||
|
||||
`TQueryFnData`
|
||||
|
||||
#### TError
|
||||
|
||||
`TError` = `Error`
|
||||
|
||||
#### TData
|
||||
|
||||
`TData` = [`InfiniteData`](../interfaces/InfiniteData.md)\<`TQueryFnData`, `unknown`\>
|
||||
|
||||
#### TQueryKey
|
||||
|
||||
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
|
||||
|
||||
#### TPageParam
|
||||
|
||||
`TPageParam` = `unknown`
|
||||
|
||||
### Parameters
|
||||
|
||||
#### injectInfiniteQueryFn
|
||||
|
||||
() => [`CreateInfiniteQueryOptions`](../interfaces/CreateInfiniteQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>
|
||||
|
||||
A function that returns infinite query options. Similar to `computed` from
|
||||
Angular, this function runs in the reactive context, so signals read inside it drive the query.
|
||||
|
||||
#### options?
|
||||
|
||||
[`InjectInfiniteQueryOptions`](../interfaces/InjectInfiniteQueryOptions.md)
|
||||
|
||||
Additional configuration.
|
||||
|
||||
### Returns
|
||||
|
||||
[`CreateInfiniteQueryResult`](../type-aliases/CreateInfiniteQueryResult.md)\<`TData`, `TError`\>
|
||||
|
||||
The infinite query result.
|
||||
Reference in New Issue
Block a user