Query Functions
Purpose and Scope
A query function is the asynchronous operation TanStack Query runs to load server state for a query key. In framework adapters, the query declaration pairs a cache identity with a function that returns a promise resolving to data or rejecting with an error. This page focuses on how to design those functions so they stay backend agnostic, how Angular users can connect Angular data clients to the promise-based contract, and where default client configuration fits. The goal is to separate the cache lifecycle from transport details: TanStack Query coordinates freshness, retries, observers, and background updates, while your query function only describes how to obtain one resource.
Sources: docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md, docs/framework/angular/guides/background-fetching-indicators.md
The most important constraint is that TanStack Query does not require a particular network library. The Angular guide states that fetching is built agnostically on promises, so a query function can use browser fetch, GraphQL clients, generated clients, Angular HttpClient after conversion, or any other asynchronous source. That makes query functions a boundary layer rather than a framework feature. Put authentication, serialization, and endpoint-specific behavior in your client code, then expose a small promise-returning function to TanStack Query. Doing this keeps query keys, invalidation, and refetching consistent even when transport implementations vary across applications.
Sources: docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md, docs/community-resources.md
Relevant Source Files
- docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md — Explains the promise-based fetching contract, shows Angular HttpClient usage inside a query function, and compares HttpClient, fetch, and specialized clients.
- docs/framework/angular/reference/functions/provideTanStackQuery.md — Documents the Angular provider setup that installs a QueryClient, including default configuration and optional features for an application.
- docs/framework/angular/guides/background-fetching-indicators.md — Shows an Angular query declaration with a query key and query function, plus local and global fetching indicators.
- docs/framework/angular/devtools.md — Shows how devtools are added through provider features, which helps inspect query functions indirectly through query and mutation state.
- docs/config.json — Places framework guides and references in the documentation navigation, confirming where Angular and other framework material is organized.
- docs/community-resources.md — Lists ecosystem utilities such as GraphQL Code Generator, Orval, Query Key Factory, and React Query Kit that commonly shape typed clients, query keys, and reusable fetching layers.
Core Primitives
The practical primitives are the query client, the query key, the query function, and the framework adapter API. A QueryClient owns caches and default options. A query key names one cache entry and should include the resource and inputs that affect the result. A query function performs the asynchronous work for that key. The adapter API, such as Angular's injection-based query function, subscribes the UI to the cache and exposes derived state. In the Angular background-fetching example, a component declares a todos query by returning options with a todos key and a fetch function, then reads pending, error, success, fetching, and data states in the template.
Sources: docs/framework/angular/reference/functions/provideTanStackQuery.md, docs/framework/angular/guides/background-fetching-indicators.md
Default query functions belong at the QueryClient layer when many queries follow the same transport convention. Instead of repeating similar request code in every query declaration, create a client with query defaults that can interpret a key or use shared metadata. The Angular provider reference shows that applications enable TanStack Query by passing a QueryClient to the provider setup, and official QueryClient documentation describes default options as part of client construction. Use this pattern when it genuinely reduces repetition, but keep per-query functions for endpoints with unusual parameters, response conversion, authorization needs, or error handling semantics.
Sources: docs/framework/angular/reference/functions/provideTanStackQuery.md
Backend-Agnostic Fetching Patterns
Angular HttpClient is a useful example because it does not natively expose a promise in the shown guide. HttpClient returns observables, while TanStack Query expects promise-based query functions, so the documentation converts the observable with RxJS helpers. The component injects HttpClient, defines a query key, and uses a query function that returns the result of converting an HTTP GET observable. That adapter step is intentionally small. HttpClient still provides Angular benefits such as testing support, interceptors, pending-task integration, and SSR request caching, while TanStack Query keeps responsibility for cache subscriptions and refetch behavior.
Sources: docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md
@Component({
// ...
})
class ExampleComponent {
private readonly http = inject(HttpClient)
readonly query = injectQuery(() => ({
queryKey: ['repoData'],
queryFn: () =>
lastValueFrom(
this.http.get('https://api.github.com/repos/tanstack/query'),
),
}))
}The same shape applies to other backends. With browser fetch, the query function can call an endpoint and return parsed JSON. With GraphQL, the query function can call a request client and return typed operation data. With generated REST clients, it can call a generated method. The repository's community resources list utilities that generate GraphQL hooks, generate TypeScript clients from OpenAPI specifications, create standardized query keys, and build reusable typed hooks. Those utilities are not required by TanStack Query, but they illustrate the intended extension point: improve the client or key layer while preserving the promise-returning query function contract.
Sources: docs/community-resources.md, docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md
Query Function Context and Key Design
A query function should derive request inputs from the same cache identity used by TanStack Query. Official reference material describes the query function as receiving a QueryFunctionContext, which includes the query key and other runtime context. Even when a local example calls a named function without parameters, design reusable functions so route parameters, filters, pagination inputs, and tenant or scope values are reflected in the key. This prevents different resources from competing for one cache entry and makes invalidation predictable. A good rule is that if changing a value changes the returned data, that value belongs in the key or in a stable default context.
Sources: docs/framework/angular/guides/background-fetching-indicators.md
Avoid hiding important request variables in closures that are not represented in the key. A closure can be convenient in a component, but it can also create confusing cache reuse when a query key stays the same while an endpoint argument changes. For Angular, returning query options from a callback lets the framework adapter reevaluate options through its reactive model, but the cache contract is still the key. The background indicator example uses a simple todos key because the example has no parameters. A real filtered todos list should include filter values, page values, or user scope so background updates and observers refer to the right data.
Sources: docs/framework/angular/guides/background-fetching-indicators.md
Execution Flow and UI Signals
At runtime, provider setup installs a QueryClient into the Angular application. Components or services declare queries through the adapter, supplying options that include a key and a query function. TanStack Query checks the cache, decides whether data is fresh enough, starts or deduplicates the promise, and notifies observers as status changes. The Angular background-fetching guide demonstrates how UI can distinguish initial pending state from background refetching. A component can show loading while the first request is pending, render an error message on failure, render data on success, and show a smaller refreshing indicator while an existing result is being updated.
Sources: docs/framework/angular/reference/functions/provideTanStackQuery.md, docs/framework/angular/guides/background-fetching-indicators.md
Global fetching indicators use the same model at application scope. The Angular guide shows a component using the fetching-count function from the adapter to render a message when any query is fetching in the background. This matters for query-function design because long-running functions, retries, and refetches become visible through shared status signals, not only in the component that started them. If a query function performs extra work after the network response, the UI remains fetching until the promise settles. Keep expensive transformation predictable, and prefer returning already-shaped data when possible so indicators match user expectations.
Sources: docs/framework/angular/guides/background-fetching-indicators.md
Provider Configuration, Devtools, and Diagnostics
Query functions become much easier to diagnose when the application is configured with the same QueryClient that the UI uses. The Angular reference documents provideTanStackQuery as the function that sets up providers necessary for TanStack Query functionality, accepting either a QueryClient instance or an InjectionToken that provides one. Optional features can be added at the same boundary. This is the correct place to attach application-wide defaults and devtools, because every query function invoked through the adapter will report through that client and its cache.
Sources: docs/framework/angular/reference/functions/provideTanStackQuery.md, docs/framework/angular/devtools.md
Devtools do not change how query functions fetch data, but they make their results observable. The Angular devtools guide explains that devtools help debug and inspect queries and mutations, and that they can be enabled by adding the devtools feature to the provider setup. Development builds include the normal path automatically, while a production subpath is available for explicitly controlled loading. When troubleshooting a query function, inspect the query key, status, data, error, observer count, and refetch behavior before changing transport code. Many apparent network bugs are actually key, freshness, retry, or disabled-query issues.
Sources: docs/framework/angular/devtools.md, docs/framework/angular/reference/functions/provideTanStackQuery.md
Compact Reference
| Concern | Use this contract | Source-backed guidance |
|---|---|---|
| Query function result | Return a Promise | TanStack Query fetching is promise based; Angular observables must be converted before returning from queryFn. |
| Angular HttpClient | Convert with RxJS helpers | The Angular guide uses lastValueFrom around an HttpClient GET observable. |
| Client setup | Provide a QueryClient | Angular applications call provideTanStackQuery with a QueryClient or InjectionToken. |
| Optional diagnostics | Add devtools feature | withDevtools can be passed as an optional provider feature for query inspection. |
| Background state | Read fetching signals | Component-level isFetching and global injectIsFetching show active background work. |
| Ecosystem clients | Keep promise boundary | OpenAPI, GraphQL, query-key, and reusable-hook utilities can generate or organize the client layer without replacing the query function contract. |
Next Steps
Use query functions as the narrowest possible bridge between a backend client and the TanStack Query cache. Start with explicit per-query functions while learning a resource, then factor repeated behavior into typed clients, query key factories, or QueryClient defaults when patterns stabilize. For Angular applications, wire the QueryClient with provideTanStackQuery, prefer HttpClient when its Angular integration benefits matter, and convert observables to promises until native promise support is available. After that, read the Query Keys, Query Options, Background Refetching, Devtools, and QueryClient Reference pages to connect fetching code with cache identity, reuse, diagnostics, and lifecycle behavior.
Sources: docs/framework/angular/angular-httpclient-and-other-data-fetching-clients.md, docs/framework/angular/reference/functions/provideTanStackQuery.md, docs/config.json