snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:13:08 +05:00
commit 3a013ccdfe
3570 changed files with 490194 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
---
id: defaultShouldDehydrateMutation
title: defaultShouldDehydrateMutation
---
```ts
function defaultShouldDehydrateMutation(mutation): boolean;
```
Defined in: [packages/query-core/src/hydration.ts:177](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L177)
The default `shouldDehydrateMutation` predicate used by `dehydrate`. Only dehydrates mutations that are
currently paused (e.g. paused by `networkMode` while offline).
## Parameters
### mutation
[`Mutation`](../classes/Mutation.md)
## Returns
`boolean`

View File

@@ -0,0 +1,23 @@
---
id: defaultShouldDehydrateQuery
title: defaultShouldDehydrateQuery
---
```ts
function defaultShouldDehydrateQuery(query): boolean;
```
Defined in: [packages/query-core/src/hydration.ts:185](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L185)
The default `shouldDehydrateQuery` predicate used by `dehydrate`. Only dehydrates queries whose status is
`'success'`.
## Parameters
### query
[`Query`](../classes/Query.md)
## Returns
`boolean`

View File

@@ -0,0 +1,43 @@
---
id: dehydrate
title: dehydrate
---
```ts
function dehydrate(client, options): DehydratedState;
```
Defined in: [packages/query-core/src/hydration.ts:207](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L207)
Dehydrates a `QueryClient`'s cache (queries and mutations) into a plain, serializable `DehydratedState`,
typically to embed in server-rendered markup and later restore into a client-side `QueryClient` via `hydrate`.
Which queries/mutations are included, and how their data/errors are transformed, is controlled by `options`,
falling back to the client's `dehydrate` default options, and finally to `defaultShouldDehydrateQuery` /
`defaultShouldDehydrateMutation`.
## Parameters
### client
[`QueryClient`](../classes/QueryClient.md)
### options
[`DehydrateOptions`](../interfaces/DehydrateOptions.md) = `{}`
## Returns
[`DehydratedState`](../interfaces/DehydratedState.md)
## Example
```ts
const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryKey: ['posts'],
queryFn: getPosts,
})
const dehydratedState = dehydrate(queryClient)
```

View File

@@ -0,0 +1,43 @@
---
id: dehydrateQuery
title: dehydrateQuery
---
```ts
function dehydrateQuery(
query,
serializeData?,
shouldRedactErrors?): DehydratedQuery;
```
Defined in: [packages/query-core/src/hydration.ts:148](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L148)
Dehydrates a single `Query` into a serializable `DehydratedQuery` snapshot. Note that most query config (e.g.
`queryFn`, `staleTime`) is not dehydrated but instead meant to be configured again when consuming the
de/rehydrated data, typically with `useQuery` on the client. If the query is still `pending`, its in-flight
promise is dehydrated too so it can be resumed on the other side instead of re-fetched.
## Parameters
### query
[`Query`](../classes/Query.md)
The query to dehydrate.
### serializeData?
`TransformerFn`
Optional transform applied to `query.state.data` before it is included in the snapshot.
### shouldRedactErrors?
(`error`) => `boolean`
Optional predicate; if it returns `false` for the promise's rejection error, that
error is kept as-is instead of being redacted.
## Returns
`DehydratedQuery`

View File

@@ -0,0 +1,52 @@
---
id: experimental_streamedQuery
title: experimental_streamedQuery
---
```ts
function experimental_streamedQuery<TQueryFnData, TData, TQueryKey>(streamFn): QueryFunction<TData, TQueryKey>;
```
Defined in: [packages/query-core/src/streamedQuery.ts:75](https://github.com/TanStack/query/blob/main/packages/query-core/src/streamedQuery.ts#L75)
This is a helper function to create a query function that streams data from an AsyncIterable.
Data will be an Array of all the chunks received.
The query will be in a 'pending' state until the first chunk of data is received, but will go to 'success' after that.
The query will stay in fetchStatus 'fetching' until the stream ends.
## Type Parameters
### TQueryFnData
`TQueryFnData` = `unknown`
### TData
`TData` = `TQueryFnData`[]
### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
## Parameters
### streamFn
`StreamedQueryParams`\<`TQueryFnData`, `TData`, `TQueryKey`\>
The function that returns an AsyncIterable to stream data from.
## Returns
[`QueryFunction`](../type-aliases/QueryFunction.md)\<`TData`, `TQueryKey`\>
## Example
```ts
await queryClient.query({
queryKey: ['data'],
queryFn: streamedQuery({
streamFn: fetchDataInChunks,
}),
})
```

View File

@@ -0,0 +1,30 @@
---
id: hashKey
title: hashKey
---
```ts
function hashKey(queryKey): string;
```
Defined in: [packages/query-core/src/utils.ts:284](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L284)
Default query & mutation keys hash function.
Hashes the value into a stable hash.
## Parameters
### queryKey
readonly `unknown`[]
## Returns
`string`
## Example
```ts
// Object keys are sorted, so key order doesn't affect the hash:
hashKey(['todos', { page: 1, filter: 'done' }]) // === '["todos",{"filter":"done","page":1}]'
```

View File

@@ -0,0 +1,49 @@
---
id: hydrate
title: hydrate
---
```ts
function hydrate(
client,
dehydratedState,
options?): void;
```
Defined in: [packages/query-core/src/hydration.ts:264](https://github.com/TanStack/query/blob/main/packages/query-core/src/hydration.ts#L264)
Restores a `DehydratedState` (as produced by `dehydrate`) into a `QueryClient`'s cache, typically to seed the
client with data already fetched on the server. `mutations` and `queries` are each optional on `dehydratedState`.
Queries not yet in the cache are built from the dehydrated snapshot; queries that already exist are only updated
when the dehydrated data is newer than what's already cached. Newly built queries have their `fetchStatus` reset
to `'idle'` so they don't hydrate stuck in a fetching state. If a dehydrated query still had an in-flight
promise, it is resumed via `query.fetch()` (reusing that promise as `initialPromise`) rather than re-invoking
`queryFn`.
## Parameters
### client
[`QueryClient`](../classes/QueryClient.md)
### dehydratedState
`Partial`\<[`DehydratedState`](../interfaces/DehydratedState.md)\>
### options?
[`HydrateOptions`](../interfaces/HydrateOptions.md)
## Returns
`void`
## Example
```ts
// dehydratedState was produced by `dehydrate` on the server
// and sent to the client, e.g. embedded in server-rendered markup.
const queryClient = new QueryClient()
hydrate(queryClient, dehydratedState)
```

View File

@@ -0,0 +1,285 @@
---
id: infiniteQueryOptions
title: infiniteQueryOptions
---
## Call Signature
```ts
function infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object & QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData, unknown>, TError>;
```
Defined in: [packages/angular-query-experimental/src/infinite-query-options.ts:181](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L181)
You can generally pass everything to `infiniteQueryOptions` that you can also pass to
`injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as
`queryClient.fetchInfiniteQuery`. `options.queryKey` is required and is the query key to generate options
for.
This overload is selected when `initialData` is set.
### 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
#### options
[`DefinedInitialDataInfiniteOptions`](../type-aliases/DefinedInitialDataInfiniteOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>
The [DefinedInitialDataInfiniteOptions](../type-aliases/DefinedInitialDataInfiniteOptions.md) to use — everything you can pass to
`injectInfiniteQuery`, with `initialData` set.
### Returns
The same options object, typed so that `queryKey` carries the inferred data type.
### See
[injectInfiniteQuery](injectInfiniteQuery.md) to run an infinite query with these options.
### Remarks
See [injectInfiniteQuery](injectInfiniteQuery.md) for examples that fetch further pages, from a button click or
automatically as the user scrolls.
### Example
```angular-ts
import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental'
export const projectsOptions = infiniteQueryOptions({
queryKey: ['projects'],
queryFn: ({ pageParam }) => fetchProjects(pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
initialData: { pages: [], pageParams: [] },
})
@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(() => projectsOptions)
}
```
## Call Signature
```ts
function infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): OmitKeyof<CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, "queryFn"> & object & QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData, unknown>, TError>;
```
Defined in: [packages/angular-query-experimental/src/infinite-query-options.ts:255](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L255)
You can generally pass everything to `infiniteQueryOptions` that you can also pass to
`injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as
`queryClient.fetchInfiniteQuery`. `options.queryKey` is required and is the query key to generate options
for.
### 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
#### options
[`UnusedSkipTokenInfiniteOptions`](../type-aliases/UnusedSkipTokenInfiniteOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>
The [UnusedSkipTokenInfiniteOptions](../type-aliases/UnusedSkipTokenInfiniteOptions.md) to use — everything you can pass to
`injectInfiniteQuery`.
### Returns
The same options object, typed so that `queryKey` carries the inferred data type.
### Remarks
See [injectInfiniteQuery](injectInfiniteQuery.md) for examples that fetch further pages, from a button click or
automatically as the user scrolls.
### Example
A parameterized factory, so the same options object can be reused per `postId`:
```angular-ts
import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental'
export const commentsOptions = (postId: string) =>
infiniteQueryOptions({
queryKey: ['post', postId, 'comments'],
queryFn: ({ pageParam }) => fetchComments(postId, pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
@Component({
selector: 'comments',
template: `
@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('1')
readonly commentsQuery = injectInfiniteQuery(() => commentsOptions(this.postId()))
}
```
### See
[injectInfiniteQuery](injectInfiniteQuery.md) to run an infinite query with these options.
## Call Signature
```ts
function infiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>(options): CreateInfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & object & QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData, unknown>, TError>;
```
Defined in: [packages/angular-query-experimental/src/infinite-query-options.ts:329](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/infinite-query-options.ts#L329)
You can generally pass everything to `infiniteQueryOptions` that you can also pass to
`injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as
`queryClient.fetchInfiniteQuery`. `options.queryKey` is required and is the query key to generate options
for.
### 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
#### options
[`UndefinedInitialDataInfiniteOptions`](../type-aliases/UndefinedInitialDataInfiniteOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`, `TPageParam`\>
The [UndefinedInitialDataInfiniteOptions](../type-aliases/UndefinedInitialDataInfiniteOptions.md) to use — everything you can pass to
`injectInfiniteQuery`.
### Returns
The same options object, typed so that `queryKey` carries the inferred data type.
### Remarks
See [injectInfiniteQuery](injectInfiniteQuery.md) for examples that fetch further pages (from a button click or
automatically as the user scrolls) and that use `skipToken` to disable the query until `postId` is set.
### Example
A parameterized factory, so the same options object can be reused per `postId`:
```angular-ts
import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental'
export const commentsOptions = (postId: string) =>
infiniteQueryOptions({
queryKey: ['post', postId, 'comments'],
queryFn: ({ pageParam }) => fetchComments(postId, pageParam),
initialPageParam: 0,
getNextPageParam: (lastPage) => lastPage.nextId,
})
@Component({
selector: 'comments',
template: `
@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('1')
readonly commentsQuery = injectInfiniteQuery(() => commentsOptions(this.postId()))
}
```
### See
[injectInfiniteQuery](injectInfiniteQuery.md) to run an infinite query with these options.

View File

@@ -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.

View File

@@ -0,0 +1,66 @@
---
id: injectIsFetching
title: injectIsFetching
---
```ts
function injectIsFetching(filters?, options?): Signal<number>;
```
Defined in: [packages/angular-query-experimental/src/inject-is-fetching.ts:63](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-fetching.ts#L63)
Injects a signal that tracks the number of queries that your application is loading or fetching in the
background (useful for app-wide loading indicators).
## Parameters
### filters?
[`QueryFilters`](../interfaces/QueryFilters.md)\<readonly `unknown`[]\>
The [QueryFilters](../interfaces/QueryFilters.md) to narrow down the matched queries.
### options?
[`InjectIsFetchingOptions`](../interfaces/InjectIsFetchingOptions.md)
Additional configuration
## Returns
`Signal`\<`number`\>
A `Signal` with the number of queries that your application is currently loading or fetching in
the background.
## Examples
```angular-ts
@Component({
selector: 'posts-fetching-indicator',
template: `
@if (isFetchingPosts()) {
<span>Refreshing posts...</span>
}
`,
})
export class PostsFetchingIndicator {
// How many queries matching the posts prefix are fetching?
readonly isFetchingPosts = injectIsFetching({ queryKey: ['posts'] })
}
```
A global loading indicator for any query fetching in the background, not just the ones on screen:
```angular-ts
@Component({
selector: 'global-loading-indicator',
template: `
@if (isFetching()) {
<div>Queries are fetching in the background...</div>
}
`,
})
export class GlobalLoadingIndicator {
readonly isFetching = injectIsFetching()
}
```

View File

@@ -0,0 +1,50 @@
---
id: injectIsMutating
title: injectIsMutating
---
```ts
function injectIsMutating(filters?, options?): Signal<number>;
```
Defined in: [packages/angular-query-experimental/src/inject-is-mutating.ts:46](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-mutating.ts#L46)
Injects a signal that tracks the number of mutations that your application currently has `pending`
(useful for app-wide loading indicators).
## Parameters
### filters?
[`MutationFilters`](../interfaces/MutationFilters.md)\<`unknown`, `Error`, `unknown`, `unknown`\>
The [MutationFilters](../interfaces/MutationFilters.md) to narrow down the matched mutations.
### options?
[`InjectIsMutatingOptions`](../interfaces/InjectIsMutatingOptions.md)
Additional configuration
## Returns
`Signal`\<`number`\>
A `Signal` with the number of mutations that your application currently has `pending`.
## Example
```angular-ts
@Component({
selector: 'posts-mutating-indicator',
template: `
@if (isMutatingPosts()) {
<span>Saving posts...</span>
}
`,
})
export class PostsMutatingIndicator {
// How many mutations matching the posts prefix are in progress?
readonly isMutatingPosts = injectIsMutating({ mutationKey: ['posts'] })
}
```

View File

@@ -0,0 +1,29 @@
---
id: injectIsRestoring
title: injectIsRestoring
---
```ts
function injectIsRestoring(options?): Signal<boolean>;
```
Defined in: [packages/angular-query-experimental/src/inject-is-restoring.ts:35](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-restoring.ts#L35)
Injects a signal that tracks whether a restore (e.g. from a persisted client, wired up via
`provideIsRestoring`) is currently in progress. `injectQuery` and friends also check this internally to
avoid race conditions between the restore and initializing queries.
## Parameters
### options?
`InjectIsRestoringOptions`
Additional configuration
## Returns
`Signal`\<`boolean`\>
A readonly `Signal<boolean>` — `true` while a restore is in progress, `false` otherwise (the
default when no `provideIsRestoring` provider is registered).

View File

@@ -0,0 +1,184 @@
---
id: injectMutation
title: injectMutation
---
```ts
function injectMutation<TData, TError, TVariables, TOnMutateResult>(injectMutationFn, options?): CreateMutationResult<TData, TError, TVariables, TOnMutateResult>;
```
Defined in: [packages/angular-query-experimental/src/inject-mutation.ts:174](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation.ts#L174)
Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects.
`injectMutation` is the function for that. Unlike queries, mutations are not run automatically.
## Type Parameters
### TData
`TData` = `unknown`
### TError
`TError` = `Error`
### TVariables
`TVariables` = `void`
### TOnMutateResult
`TOnMutateResult` = `unknown`
## Parameters
### injectMutationFn
() => [`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>
A function that returns mutation options. Similar to `computed` from Angular,
this function runs in the reactive context, so signals read inside it drive the mutation's options.
### options?
[`InjectMutationOptions`](../interfaces/InjectMutationOptions.md)
Additional configuration
## Returns
[`CreateMutationResult`](../type-aliases/CreateMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>
The mutation result. Value fields are exposed as a `Signal` — read `data`/`error` by calling them
(e.g. `mutation.data()`) — while function fields (`mutate`, `mutateAsync`, `reset`) are called directly,
unchanged. `isSuccess`/`isError`/`isPending`/`isIdle` are type-guard methods you can call to narrow whether
`data` is defined.
## Remarks
`mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a
second argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to
the shared mutation definition. Callbacks defined in `injectMutationFn` fire for every mutation; per-call
callbacks fire only for the latest call you've made — `mutateAsync` gives you a promise per call instead,
so you can await `Promise.all`/`Promise.allSettled` over several calls and see each one's outcome.
## See
[mutationOptions](mutationOptions.md) to share these options across multiple `injectMutation` call sites, or to look
the mutation up elsewhere via its `mutationKey` (e.g. with `injectMutationState`).
## Examples
```angular-ts
@Component({
selector: 'todos',
template: `
@if (addMutation.isPending()) {
<span>Adding todo...</span>
} @else if (addMutation.isError()) {
<div>An error occurred: {{ addMutation.error()?.message }}</div>
}
<button (click)="addMutation.mutate('Item')">Add</button>
`,
})
export class Todos {
readonly #queryClient = inject(QueryClient)
readonly addMutation = injectMutation(() => ({
mutationFn: addTodo,
onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }),
}))
}
```
Optimistic update via `onMutate`, rolling back on `onError`:
```angular-ts
@Component({
selector: 'todos',
template: `<button (click)="addMutation.mutate('Item')">Add</button>`,
})
export class Todos {
readonly #queryClient = inject(QueryClient)
readonly addMutation = injectMutation(() => ({
mutationFn: addTodo,
onMutate: async (newTodo) => {
await this.#queryClient.cancelQueries({ queryKey: ['todos'] })
const previousTodos = this.#queryClient.getQueryData<Array<string>>(['todos'])
this.#queryClient.setQueryData<Array<string>>(['todos'], (old) => [
...(old ?? []),
newTodo,
])
// Passed to `onError` as `onMutateResult` if the mutation fails.
return { previousTodos }
},
onError: (_err, _newTodo, onMutateResult) => {
this.#queryClient.setQueryData(['todos'], onMutateResult?.previousTodos)
},
onSettled: () => {
this.#queryClient.invalidateQueries({ queryKey: ['todos'] })
},
}))
}
```
Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a promise per
call instead, so you can wait for all of them when they succeed:
```angular-ts
@Component({
selector: 'todos',
template: `
<button (click)="handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])">Add all</button>
`,
})
export class Todos {
readonly #queryClient = inject(QueryClient)
readonly addMutation = injectMutation(() => ({
mutationFn: addTodo,
onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }),
}))
async handleAddAll(todos: Array<string>) {
try {
await Promise.all(todos.map((todo) => this.addMutation.mutateAsync(todo)))
} catch (error) {
console.error('Failed to add todos:', error)
}
}
}
```
If some of the mutations above can fail independently of the others, and you want to know which ones did —
rather than losing that information the moment the first one rejects — swap `Promise.all` for
`Promise.allSettled`:
```angular-ts
@Component({
selector: 'todos',
template: `
<button (click)="handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])">Add all</button>
`,
})
export class Todos {
readonly #queryClient = inject(QueryClient)
readonly addMutation = injectMutation(() => ({
mutationFn: addTodo,
onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }),
}))
async handleAddAll(todos: Array<string>) {
const addResults = await Promise.allSettled(
todos.map((todo) => this.addMutation.mutateAsync(todo)),
)
addResults.forEach((addResult, index) => {
if (addResult.status === 'rejected') {
console.error(`Failed to add "${todos[index]}":`, addResult.reason)
}
})
}
}
```

View File

@@ -0,0 +1,88 @@
---
id: injectMutationState
title: injectMutationState
---
```ts
function injectMutationState<TResult>(injectMutationStateFn, options?): Signal<TResult[]>;
```
Defined in: [packages/angular-query-experimental/src/inject-mutation-state.ts:106](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-mutation-state.ts#L106)
Injects a signal that gives you access to all mutations in the `MutationCache`. You can pass `filters`
([MutationFilters](../interfaces/MutationFilters.md)) to narrow down your mutations, and `select` to transform the mutation state.
## Type Parameters
### TResult
`TResult` = [`MutationState`](../interfaces/MutationState.md)\<`unknown`, `Error`, `unknown`, `unknown`\>
## Parameters
### injectMutationStateFn
() => `MutationStateOptions`\<`TResult`\>
A function returning the `filters` to narrow down matched mutations, and an
optional `select` to transform the mutation state. Similar to `computed` from Angular, this function runs
in the reactive context, so signals read inside it re-narrow the matched mutations.
### options?
[`InjectMutationStateOptions`](../interfaces/InjectMutationStateOptions.md)
Additional configuration
## Returns
`Signal`\<`TResult`[]\>
A `Signal` with an Array of whatever `select` returns for each matching mutation.
## Examples
Get all variables of all running mutations:
```angular-ts
@Component({
selector: 'pending-posts',
template: `{{ pendingVariables().length }} posts saving...`,
})
export class PendingPosts {
readonly pendingVariables = injectMutationState(() => ({
filters: { status: 'pending' },
select: (mutation) => mutation.state.variables,
}))
}
```
Get all data for specific mutations via the `mutationKey`:
```angular-ts
const mutationKey = ['posts']
@Component({
selector: 'posts',
template: `
<button (click)="createPost()">
Create post ({{ savedPosts().length }} saved so far)
</button>
`,
})
export class Posts {
// Some mutation that we want to get the state for
readonly createPostMutation = injectMutation(() => ({
mutationKey,
mutationFn: createPosts,
}))
readonly savedPosts = injectMutationState(() => ({
// this mutation key needs to match the mutation key of the given mutation (see above)
filters: { mutationKey, status: 'success' },
select: (mutation) => mutation.state.data,
}))
createPost() {
this.createPostMutation.mutate(['New Post'])
}
}
```

View File

@@ -0,0 +1,263 @@
---
id: injectQuery
title: injectQuery
---
## Call Signature
```ts
function injectQuery<TQueryFnData, TError, TData, TQueryKey>(injectQueryFn, options?): DefinedCreateQueryResult<TData, TError>;
```
Defined in: [packages/angular-query-experimental/src/inject-query.ts:69](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L69)
This overload is selected when `initialData` is set on the options returned by `injectQueryFn`, so the
resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`).
### Type Parameters
#### TQueryFnData
`TQueryFnData` = `unknown`
#### TError
`TError` = `Error`
#### TData
`TData` = `TQueryFnData`
#### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
### Parameters
#### injectQueryFn
() => [`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
A function returning the [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you
can pass to `injectQuery`, with `initialData` set. Similar to `computed` from Angular, this function runs
in the reactive context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query.
#### options?
[`InjectQueryOptions`](../interfaces/InjectQueryOptions.md)
Additional configuration
### Returns
[`DefinedCreateQueryResult`](../type-aliases/DefinedCreateQueryResult.md)\<`TData`, `TError`\>
The query result, typed so that `data` is never `undefined` (unless a `select` changes `TData` to
include `undefined`).
### See
- https://tanstack.com/query/latest/docs/framework/angular/guides/queries
- [queryOptions](queryOptions.md) to share these options between `injectQuery` and imperative APIs like
`queryClient.fetchQuery`.
### Example
```angular-ts
@Component({
selector: 'posts',
template: `
<!-- `postsQuery.data()` is `Post[]`, never `undefined`, thanks to `initialData` — even if a
refetch fails, so the list stays visible alongside the error. -->
@if (postsQuery.isError()) {
<span>Error: {{ postsQuery.error()?.message }}</span>
}
<ul>
@for (post of postsQuery.data(); track post.id) {
<li>{{ post.title }}</li>
}
</ul>
`,
})
export class Posts {
readonly postsQuery = injectQuery(() => ({
queryKey: ['posts'],
queryFn: fetchPosts,
initialData: [],
}))
}
```
## Call Signature
```ts
function injectQuery<TQueryFnData, TError, TData, TQueryKey>(injectQueryFn, options?): CreateQueryResult<TData, TError>;
```
Defined in: [packages/angular-query-experimental/src/inject-query.ts:158](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L158)
Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key.
### Type Parameters
#### TQueryFnData
`TQueryFnData` = `unknown`
#### TError
`TError` = `Error`
#### TData
`TData` = `TQueryFnData`
#### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
### Parameters
#### injectQueryFn
() => [`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
A function returning the [UndefinedInitialDataOptions](../type-aliases/UndefinedInitialDataOptions.md) to use — everything
you can pass to `injectQuery`. Similar to `computed` from Angular, this function runs in the reactive
context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query.
#### options?
[`InjectQueryOptions`](../interfaces/InjectQueryOptions.md)
Additional configuration
### Returns
[`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<`TData`, `TError`\>
The query result. `status()` is `'pending'` if there is no cached data to display, `'error'` if
the last fetch attempt failed, or `'success'` if the query has data to display. `isPending`/`isSuccess`/
`isError` are type-guard methods for convenience.
### See
- https://tanstack.com/query/latest/docs/framework/angular/guides/queries
- [queryOptions](queryOptions.md) to share these options between `injectQuery` and imperative APIs like
`queryClient.fetchQuery`.
### Examples
```angular-ts
@Component({
selector: 'posts',
template: `
@if (postsQuery.isPending()) {
Loading...
} @else if (postsQuery.isError()) {
<span>Error: {{ postsQuery.error()?.message }}</span>
} @else {
<ul>
@for (post of postsQuery.data(); track post.id) {
<li>{{ post.title }}</li>
}
</ul>
}
`,
})
export class Posts {
readonly postsQuery = injectQuery(() => ({
queryKey: ['posts'],
queryFn: fetchPosts,
}))
}
```
Similar to `computed` from Angular, the function passed to `injectQuery` runs in the reactive context. In
the example below, the query is automatically enabled and executed when the filter signal changes to a
truthy value. When the filter signal changes back to a falsy value, the query is disabled.
```angular-ts
@Component({
selector: 'posts',
template: `
<input [ngModel]="filter()" (ngModelChange)="filter.set($event)" />
@if (postsQuery.isPending()) {
Loading...
} @else if (postsQuery.isError()) {
<span>Error: {{ postsQuery.error()?.message }}</span>
} @else {
<ul>
@for (post of postsQuery.data(); track post.id) {
<li>{{ post.title }}</li>
}
</ul>
}
`,
})
export class Posts {
readonly filter = signal('')
readonly postsQuery = injectQuery(() => ({
queryKey: ['posts', this.filter()],
queryFn: () => fetchPosts(this.filter()),
// Signals can be combined with expressions
enabled: !!this.filter(),
}))
}
```
## Call Signature
```ts
function injectQuery<TQueryFnData, TError, TData, TQueryKey>(injectQueryFn, options?): CreateQueryResult<TData, TError>;
```
Defined in: [packages/angular-query-experimental/src/inject-query.ts:185](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query.ts#L185)
This overload accepts the general [CreateQueryOptions](../interfaces/CreateQueryOptions.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
`injectQuery` in your own helper function that forwards caller-provided options.
### Type Parameters
#### TQueryFnData
`TQueryFnData` = `unknown`
#### TError
`TError` = `Error`
#### TData
`TData` = `TQueryFnData`
#### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
### Parameters
#### injectQueryFn
() => [`CreateQueryOptions`](../interfaces/CreateQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
A function that returns query options. Similar to `computed` from Angular, this
function runs in the reactive context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive
the query.
#### options?
[`InjectQueryOptions`](../interfaces/InjectQueryOptions.md)
Additional configuration
### Returns
[`CreateQueryResult`](../type-aliases/CreateQueryResult.md)\<`TData`, `TError`\>
The query result.
### See
https://tanstack.com/query/latest/docs/framework/angular/guides/queries

View File

@@ -0,0 +1,36 @@
---
id: injectQueryClient
title: injectQueryClient
---
```ts
function injectQueryClient(injectOptions): QueryClient;
```
Defined in: [packages/angular-query-experimental/src/inject-query-client.ts:18](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-query-client.ts#L18)
Injects a `QueryClient` instance and allows passing a custom injector.
## Parameters
### injectOptions
`InjectOptions` & `object` = `{}`
Type of the options argument to inject and optionally a custom injector.
## Returns
[`QueryClient`](../classes/QueryClient.md)
The `QueryClient` instance.
## Deprecated
Use `inject(QueryClient)` instead.
If you need to get a `QueryClient` from a custom injector, use `injector.get(QueryClient)`.
**Example**
```ts
const queryClient = injectQueryClient();
```

View File

@@ -0,0 +1,24 @@
---
id: isCancelledError
title: isCancelledError
---
```ts
function isCancelledError(value): value is CancelledError;
```
Defined in: [packages/query-core/src/retryer.ts:90](https://github.com/TanStack/query/blob/main/packages/query-core/src/retryer.ts#L90)
## Parameters
### value
`any`
## Returns
`value is CancelledError`
## Deprecated
Use instanceof `CancelledError` instead.

View File

@@ -0,0 +1,40 @@
---
id: keepPreviousData
title: keepPreviousData
---
```ts
function keepPreviousData<T>(previousData): T | undefined;
```
Defined in: [packages/query-core/src/utils.ts:493](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L493)
Intended to be passed as a query's `placeholderData` option, for example
`placeholderData: keepPreviousData`. Instead of resetting the query's data to `undefined` while a new
query key is fetching, it keeps displaying the previously fetched data until the new data arrives.
## Type Parameters
### T
`T`
## Parameters
### previousData
`T` | `undefined`
## Returns
`T` \| `undefined`
## Example
```ts
new QueryObserver(queryClient, {
queryKey: ['posts', page],
queryFn: () => fetchPosts(page),
placeholderData: keepPreviousData,
})
```

View File

@@ -0,0 +1,38 @@
---
id: matchMutation
title: matchMutation
---
```ts
function matchMutation(filters, mutation): boolean;
```
Defined in: [packages/query-core/src/utils.ts:237](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L237)
Checks whether a mutation matches the given [MutationFilters](../interfaces/MutationFilters.md).
Every filter that is specified must match; filters that are left unspecified are ignored.
If a `mutationKey` filter is provided but the mutation has no `mutationKey` of its own, it does not match.
## Parameters
### filters
[`MutationFilters`](../interfaces/MutationFilters.md)
### mutation
[`Mutation`](../classes/Mutation.md)\<`any`, `any`\>
## Returns
`boolean`
## Example
```ts
const mutationCache = queryClient.getMutationCache()
const matchingMutations = mutationCache
.getAll()
.filter((mutation) => matchMutation({ mutationKey: ['addPost'] }, mutation))
```

View File

@@ -0,0 +1,37 @@
---
id: matchQuery
title: matchQuery
---
```ts
function matchQuery(filters, query): boolean;
```
Defined in: [packages/query-core/src/utils.ts:175](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L175)
Checks whether a query matches the given [QueryFilters](../interfaces/QueryFilters.md).
Every filter that is specified must match; filters that are left unspecified are ignored.
## Parameters
### filters
[`QueryFilters`](../interfaces/QueryFilters.md)
### query
[`Query`](../classes/Query.md)\<`any`, `any`, `any`, `any`\>
## Returns
`boolean`
## Example
```ts
const queryCache = queryClient.getQueryCache()
const matchingQueries = queryCache
.getAll()
.filter((query) => matchQuery({ queryKey: ['posts'] }, query))
```

View File

@@ -0,0 +1,167 @@
---
id: mutationOptions
title: mutationOptions
---
## Call Signature
```ts
function mutationOptions<TData, TError, TVariables, TOnMutateResult>(options): WithRequired<CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>, "mutationKey">;
```
Defined in: [packages/angular-query-experimental/src/mutation-options.ts:40](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/mutation-options.ts#L40)
You can generally pass everything to `mutationOptions` that you can also pass to `injectMutation`. A
`mutationKey` is required on this overload so the mutation can be looked up later, e.g. with
`injectMutationState`.
### Type Parameters
#### TData
`TData` = `unknown`
#### TError
`TError` = `Error`
#### TVariables
`TVariables` = `void`
#### TOnMutateResult
`TOnMutateResult` = `unknown`
### Parameters
#### options
[`WithRequired`](../type-aliases/WithRequired.md)\<[`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>, `"mutationKey"`\>
The mutation options to use, identical to what you'd pass to `injectMutation`, with a
required `mutationKey`.
### Returns
[`WithRequired`](../type-aliases/WithRequired.md)\<[`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>, `"mutationKey"`\>
The same options object, unchanged.
### See
[injectMutation](injectMutation.md) to run the mutation these options describe.
### Example
Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator:
```angular-ts
import { mutationOptions, injectMutationState } from '@tanstack/angular-query-experimental'
const createPostOptions = mutationOptions({
mutationKey: ['posts', 'create'],
mutationFn: createPost,
})
@Component({
selector: 'saving-indicator',
template: `
@if (isCreatingPost()) {
<span>Saving…</span>
}
`,
})
export class SavingIndicator {
readonly #pendingCreates = injectMutationState(() => ({
filters: { mutationKey: createPostOptions.mutationKey, status: 'pending' },
}))
readonly isCreatingPost = computed(() => this.#pendingCreates().length > 0)
}
```
## Call Signature
```ts
function mutationOptions<TData, TError, TVariables, TOnMutateResult>(options): Omit<CreateMutationOptions<TData, TError, TVariables, TOnMutateResult>, "mutationKey">;
```
Defined in: [packages/angular-query-experimental/src/mutation-options.ts:98](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/mutation-options.ts#L98)
You can generally pass everything to `mutationOptions` that you can also pass to `injectMutation`. No
`mutationKey` is required on this overload — use this when you don't need to target the mutation via a
`mutationKey` filter later (e.g. with `injectMutationState`); it can still be observed through other
filters, such as `status`.
### Type Parameters
#### TData
`TData` = `unknown`
#### TError
`TError` = `Error`
#### TVariables
`TVariables` = `void`
#### TOnMutateResult
`TOnMutateResult` = `unknown`
### Parameters
#### options
`Omit`\<[`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>, `"mutationKey"`\>
The mutation options to use, identical to what you'd pass to `injectMutation`, without a
`mutationKey`.
### Returns
`Omit`\<[`CreateMutationOptions`](../interfaces/CreateMutationOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\>, `"mutationKey"`\>
The same options object, unchanged.
### See
[injectMutation](injectMutation.md) to run the mutation these options describe.
### Remarks
See the other overload's example for looking a mutation up via `injectMutationState`.
### Example
Sharing options across services, so `QueriesService` stays the single place a mutation is defined:
```angular-ts
import { mutationOptions, injectMutation } from '@tanstack/angular-query-experimental'
@Injectable({ providedIn: 'root' })
export class QueriesService {
readonly #queryClient = inject(QueryClient)
updatePost(id: number) {
return mutationOptions({
mutationFn: (post: Partial<Post>) => putPost(id, post),
onSuccess: (newPost) => this.#queryClient.setQueryData(['posts', id], newPost),
})
}
}
@Component({
selector: 'post',
template: `<button (click)="save()">Save</button>`,
})
export class Post {
readonly queries = inject(QueriesService)
readonly id = signal(0)
readonly updatePostMutation = injectMutation(() => this.queries.updatePost(this.id()))
save() {
this.updatePostMutation.mutate({ title: 'New Title' })
}
}
```

View File

@@ -0,0 +1,32 @@
---
id: noop
title: noop
---
## Call Signature
```ts
function noop(): void;
```
Defined in: [packages/query-core/src/utils.ts:119](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L119)
A function that does nothing.
### Returns
`void`
## Call Signature
```ts
function noop(): undefined;
```
Defined in: [packages/query-core/src/utils.ts:120](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L120)
A function that does nothing.
### Returns
`undefined`

View File

@@ -0,0 +1,26 @@
---
id: partialMatchKey
title: partialMatchKey
---
```ts
function partialMatchKey(a, b): boolean;
```
Defined in: [packages/query-core/src/utils.ts:300](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L300)
Checks if key `b` partially matches with key `a`.
## Parameters
### a
readonly `unknown`[]
### b
readonly `unknown`[]
## Returns
`boolean`

View File

@@ -0,0 +1,36 @@
---
id: provideAngularQuery
title: provideAngularQuery
---
```ts
function provideAngularQuery(queryClient): Provider[];
```
Defined in: [packages/angular-query-experimental/src/providers.ts:121](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L121)
Sets up providers necessary to enable TanStack Query functionality for Angular applications.
Allows configuring a `QueryClient`.
## Parameters
### queryClient
[`QueryClient`](../classes/QueryClient.md)
A `QueryClient` instance.
## Returns
`Provider`[]
A set of providers to set up TanStack Query.
## See
https://tanstack.com/query/v5/docs/framework/angular/quick-start
## Deprecated
Use `provideTanStackQuery` instead.

View File

@@ -0,0 +1,28 @@
---
id: provideIsRestoring
title: provideIsRestoring
---
```ts
function provideIsRestoring(isRestoring): Provider;
```
Defined in: [packages/angular-query-experimental/src/inject-is-restoring.ts:48](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/inject-is-restoring.ts#L48)
Registers a provider for the restore state read by `injectIsRestoring`. Wire this up wherever you drive a
restore yourself — e.g. a persist-client integration — so `injectQuery` and friends can defer subscribing
to their observer (avoiding a race with the restore) until the restore signal flips back to `false`.
## Parameters
### isRestoring
`Signal`\<`boolean`\>
A readonly `Signal<boolean>` that tracks the restore state.
## Returns
`Provider`
A provider for the `isRestoring` signal.

View File

@@ -0,0 +1,39 @@
---
id: provideQueryClient
title: provideQueryClient
---
```ts
function provideQueryClient(queryClient): Provider;
```
Defined in: [packages/angular-query-experimental/src/providers.ts:22](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L22)
Usually [provideTanStackQuery](provideTanStackQuery.md) is used once to set up TanStack Query and the
[`QueryClient`](https://tanstack.com/query/latest/docs/reference/QueryClient) for the entire application —
it calls `provideQueryClient` internally. Use `provideQueryClient` directly to provide a different
`QueryClient` instance for part of the application, or for unit testing.
## Parameters
### queryClient
A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`.
[`QueryClient`](../classes/QueryClient.md) | `InjectionToken`\<[`QueryClient`](../classes/QueryClient.md)\>
## Returns
`Provider`
A provider object that can be used to provide the `QueryClient` instance.
## Example
Providing a test-only `QueryClient` in a component test, without wiring up `provideTanStackQuery`'s other
defaults:
```ts
TestBed.configureTestingModule({
providers: [provideQueryClient(new QueryClient())],
})
```

View File

@@ -0,0 +1,88 @@
---
id: provideTanStackQuery
title: provideTanStackQuery
---
```ts
function provideTanStackQuery(queryClient, ...features): Provider[];
```
Defined in: [packages/angular-query-experimental/src/providers.ts:102](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L102)
Sets up providers necessary to enable TanStack Query functionality for Angular applications. Allows
configuring a `QueryClient` and optional features such as developer tools.
## Parameters
### queryClient
A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`.
[`QueryClient`](../classes/QueryClient.md) | `InjectionToken`\<[`QueryClient`](../classes/QueryClient.md)\>
### features
...[`QueryFeatures`](../type-aliases/QueryFeatures.md)[]
Optional features to configure additional Query functionality.
## Returns
`Provider`[]
A set of providers to set up TanStack Query.
## See
- https://tanstack.com/query/v5/docs/framework/angular/quick-start
- withDevtools
## Examples
```ts
import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental'
bootstrapApplication(AppComponent, {
providers: [provideTanStackQuery(new QueryClient())],
})
```
The same, in an `NgModule`-based application:
```ts
import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental'
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [provideTanStackQuery(new QueryClient())],
bootstrap: [AppComponent],
})
export class AppModule {}
```
Enabling optional developer tools by adding `withDevtools` — by default, the tools are then loaded when
your app is in development mode:
```ts
import {
provideTanStackQuery,
withDevtools,
QueryClient,
} from '@tanstack/angular-query-experimental'
bootstrapApplication(AppComponent, {
providers: [provideTanStackQuery(new QueryClient(), withDevtools())],
})
```
Using an `InjectionToken` for the `QueryClient` — an advanced optimization that lets TanStack Query be
absent from the main application bundle, useful for including it on lazy-loaded routes only while still
sharing a `QueryClient`. This is a small optimization; for most applications it's preferable to provide
the `QueryClient` in the main application config, as in the examples above:
```ts
export const MY_QUERY_CLIENT = new InjectionToken('', {
factory: () => new QueryClient(),
})
// In a lazy loaded route or lazy loaded component's providers array:
providers: [provideTanStackQuery(MY_QUERY_CLIENT)]
```

View File

@@ -0,0 +1,38 @@
---
id: queryFeature
title: queryFeature
---
```ts
function queryFeature<TFeatureKind>(kind, providers): QueryFeature<TFeatureKind>;
```
Defined in: [packages/angular-query-experimental/src/providers.ts:143](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/providers.ts#L143)
Helper function to create an object that represents a Query feature.
## Type Parameters
### TFeatureKind
`TFeatureKind` *extends* `"Devtools"` \| `"PersistQueryClient"`
## Parameters
### kind
`TFeatureKind`
The kind of feature, e.g. `'Devtools'`.
### providers
`Provider`[]
The Angular providers this feature contributes to `provideTanStackQuery`.
## Returns
[`QueryFeature`](../interfaces/QueryFeature.md)\<`TFeatureKind`\>
A Query feature.

View File

@@ -0,0 +1,274 @@
---
id: queryOptions
title: queryOptions
---
## Call Signature
```ts
function queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): Omit<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>, "queryFn"> & object & QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>;
```
Defined in: [packages/angular-query-experimental/src/query-options.ts:151](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L151)
You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options
can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is
required and is the query key to generate options for.
This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless
a `select` changes `TData` to include `undefined`).
### Type Parameters
#### TQueryFnData
`TQueryFnData` = `unknown`
#### TError
`TError` = `Error`
#### TData
`TData` = `TQueryFnData`
#### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
### Parameters
#### options
[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
The [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you can pass to `injectQuery`,
with `initialData` set.
### Returns
The same options object, typed so that `queryKey` carries the inferred data type.
### See
- [injectQuery](injectQuery.md) to run a query with these options.
- [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
### Example
```angular-ts
import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'
export const postsOptions = queryOptions({
queryKey: ['posts'],
queryFn: fetchPosts,
initialData: [],
})
@Component({
selector: 'posts',
template: `
<!-- `postsQuery.data()` is never `undefined`, thanks to `initialData` — even if a refetch
fails, so the list stays visible alongside the error. -->
@if (postsQuery.isError()) {
<span>Error: {{ postsQuery.error()?.message }}</span>
}
<ul>
@for (post of postsQuery.data(); track post.id) {
<li>{{ post.title }}</li>
}
</ul>
`,
})
export class Posts {
readonly postsQuery = injectQuery(() => postsOptions)
}
```
## Call Signature
```ts
function queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): OmitKeyof<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>, "queryFn"> & object & QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>;
```
Defined in: [packages/angular-query-experimental/src/query-options.ts:200](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L200)
You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options
can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is
required and is the query key to generate options for.
### Type Parameters
#### TQueryFnData
`TQueryFnData` = `unknown`
#### TError
`TError` = `Error`
#### TData
`TData` = `TQueryFnData`
#### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
### Parameters
#### options
[`UnusedSkipTokenOptions`](../type-aliases/UnusedSkipTokenOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
The [UnusedSkipTokenOptions](../type-aliases/UnusedSkipTokenOptions.md) to use — everything you can pass to `injectQuery`.
### Returns
The same options object, typed so that `queryKey` carries the inferred data type.
### See
- [injectQuery](injectQuery.md) to run a query with these options.
- [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
### Example
A parameterized factory, so the same options object can be reused per `id`:
```angular-ts
import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'
export const postOptions = (id: string) =>
queryOptions({
queryKey: ['post', id],
queryFn: () => fetchPost(id),
})
@Component({
selector: 'post',
template: `
@if (postQuery.isPending()) {
Loading...
} @else if (postQuery.isError()) {
<span>Error: {{ postQuery.error()?.message }}</span>
} @else {
<h1>{{ postQuery.data().title }}</h1>
}
`,
})
export class Post {
readonly id = signal('1')
readonly postQuery = injectQuery(() => postOptions(this.id()))
}
```
## Call Signature
```ts
function queryOptions<TQueryFnData, TError, TData, TQueryKey>(options): CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey> & object & QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>;
```
Defined in: [packages/angular-query-experimental/src/query-options.ts:281](https://github.com/TanStack/query/blob/main/packages/angular-query-experimental/src/query-options.ts#L281)
You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options
can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is
required and is the query key to generate options for.
### Type Parameters
#### TQueryFnData
`TQueryFnData` = `unknown`
#### TError
`TError` = `Error`
#### TData
`TData` = `TQueryFnData`
#### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
### Parameters
#### options
[`UndefinedInitialDataOptions`](../type-aliases/UndefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
The [UndefinedInitialDataOptions](../type-aliases/UndefinedInitialDataOptions.md) to use — everything you can pass to `injectQuery`.
### Returns
The same options object, typed so that `queryKey` carries the inferred data type.
### See
- [injectQuery](injectQuery.md) to run a query with these options.
- [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
### Remarks
This is the only overload that accepts `queryFn: skipToken`, shown below.
### Examples
A parameterized factory, so the same options object can be reused per `id`:
```angular-ts
import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental'
export const postOptions = (id: string) =>
queryOptions({
queryKey: ['post', id],
queryFn: () => fetchPost(id),
})
@Component({
selector: 'post',
template: `
@if (postQuery.isPending()) {
Loading...
} @else if (postQuery.isError()) {
<span>Error: {{ postQuery.error()?.message }}</span>
} @else {
<h1>{{ postQuery.data().title }}</h1>
}
`,
})
export class Post {
readonly id = signal('1')
readonly postQuery = injectQuery(() => postOptions(this.id()))
}
```
A factory that disables the query, type safe, until `postId` is set:
```angular-ts
import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query-experimental'
export const postOptions = (postId: number | undefined) =>
queryOptions({
queryKey: ['post', postId],
queryFn: postId != null ? () => fetchPost(postId) : skipToken,
})
@Component({
selector: 'post',
template: `
@if (postId() == null) {
Select a post
} @else if (postQuery.isPending()) {
Loading...
} @else if (postQuery.isError()) {
<span>Error: {{ postQuery.error()?.message }}</span>
} @else {
<h1>{{ postQuery.data().title }}</h1>
}
`,
})
export class Post {
readonly postId = signal<number | undefined>(undefined)
readonly postQuery = injectQuery(() => postOptions(this.postId()))
}
```

View File

@@ -0,0 +1,41 @@
---
id: replaceEqualDeep
title: replaceEqualDeep
---
```ts
function replaceEqualDeep<T>(
a,
b,
depth?): T;
```
Defined in: [packages/query-core/src/utils.ts:339](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L339)
This function returns `a` if `b` is deeply equal.
If not, it will replace any deeply equal children of `b` with those of `a`.
This can be used for structural sharing between JSON values for example.
## Type Parameters
### T
`T`
## Parameters
### a
`unknown`
### b
`T`
### depth?
`number`
## Returns
`T`

View File

@@ -0,0 +1,45 @@
---
id: shouldThrowError
title: shouldThrowError
---
```ts
function shouldThrowError<T>(throwOnError, params): boolean;
```
Defined in: [packages/query-core/src/utils.ts:576](https://github.com/TanStack/query/blob/main/packages/query-core/src/utils.ts#L576)
Resolves a `throwOnError` option to a boolean.
If `throwOnError` is a function, it is called with `params` (e.g. the error and, depending on the caller,
additional context such as the query or mutation) and its result is returned, allowing the throwing
behavior to be decided per error. Otherwise, `throwOnError` itself is coerced to a boolean (`undefined`
resolves to `false`).
## Type Parameters
### T
`T` *extends* (...`args`) => `boolean`
## Parameters
### throwOnError
`boolean` | `T` | `undefined`
### params
`Parameters`\<`T`\>
## Returns
`boolean`
## Example
```ts
const throwOnError =
query.state.error && typeof options.throwOnError === 'function'
? shouldThrowError(options.throwOnError, [query.state.error, query])
: options.throwOnError
```