Centralize query configuration
Several components use the same resource query and should share one cache definition.
TanStack · Function
queryOptions builds reusable, type-safe TanStack Query configurations. The returned options work with hooks and imperative QueryClient APIs while carrying query data and error types through the query key.
queryOptions packages a query key and its behavior into a reusable, type-aware options object. Its returned value brands the key with the query function's data and error types, allowing the same configuration to work with hooks and imperative QueryClient methods while preserving inference.
function queryOptions<TQueryFnData, TError, TData, TQueryKey>(options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>;| Name | Type | Description |
|---|---|---|
options | DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> | UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> | UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> | A query options object, including the required queryKey and the query behavior accepted by useQuery. |
The supplied query options augmented with a QueryKeyWithDataTag carrying the query function's data and error types.
import { queryOptions, useQuery } from '@tanstack/react-query'
type Todo = { id: number; title: string }
async function fetchTodos(): Promise<Todo[]> {
const response = await fetch('/api/todos')
if (!response.ok) throw new Error('Request failed')
return response.json()
}
const todosOptions = queryOptions({
queryKey: ['todos'],
queryFn: fetchTodos,
})
export function Todos() {
const { data = [] } = useQuery(todosOptions)
return <ul>{data.map(todo => <li key={todo.id}>{todo.title}</li>)}</ul>
}Define one typed options object and reuse it with a query hook or imperative QueryClient API.
Several components use the same resource query and should share one cache definition.
A feature needs both a React hook and an imperative QueryClient operation.
A TypeScript codebase needs query-key-based inference for fetched and selected data.
queryOptions creates a reusable query configuration from options such as queryKey and queryFn. The returned object carries query-function data and error types through the query key, improving inference when reused.
Follow-up: Why is that useful beyond hooks? The same options can be passed to imperative QueryClient APIs, so one definition can coordinate declarative and imperative access.
Its options parameter is a QueryOptions-shaped object, and queryKey is required. The function returns the corresponding options object with a typed query-key data tag.
Follow-up: What must remain consistent when reusing it? The query key and query function should describe the same resource so cache identity and inferred data remain aligned.
A queryOptions result can generally be passed to useQuery and to imperative APIs such as queryClient.query. This makes the query definition reusable instead of duplicating its key and fetch behavior.
Follow-up: How would you share a parameterized query? Create a function that accepts the parameter and returns queryOptions with that parameter included in queryKey and used by queryFn.
useQueryQueryClientqueryClient.queryQueryKeyWithDataTagDefinedInitialDataOptions