Avoid an initial loading state
A server-rendered page already has the record needed by a query.
TanStack · Pipe
initialData prepopulates a query's cache when no cached query exists, allowing the query to render without an initial loading state. The value persists in the cache and is stale by default unless freshness is configured.
initialData seeds a query's cache only when that query has not already been created or cached. It may be a value or a synchronously evaluated function, which runs once during shared query initialization. The seeded value is persisted and is stale by default; staleTime or initialDataUpdatedAt controls when TanStack Query considers it fresh.
useQuery({ queryKey, queryFn, initialData, initialDataUpdatedAt })| Name | Type | Description |
|---|---|---|
initialData | TQueryFnData | (() => TQueryFnData | undefined) | undefined | Initial query data, or a function that synchronously returns it. |
initialDataUpdatedAt | number | (() => number | undefined) | undefined | Time in milliseconds when the initial data was last updated, or a function returning that time. |
The query result is initialized from the supplied data; when defined initial data is provided, the relevant useQuery overload exposes data as non-undefined unless select changes its type.
initialData for placeholder, partial, or incomplete results; use placeholderData instead because the value is persisted.initialData does not replace the need for a query function when the enabled query must fetch.import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'
const queryClient = new QueryClient()
type Todo = { id: number; title: string }
async function fetchTodos(): Promise<Todo[]> {
return [{ id: 1, title: 'Learn TanStack Query' }]
}
function Todos() {
const query = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
initialData: [{ id: 0, title: 'Initial todo' }],
initialDataUpdatedAt: Date.now(),
})
return <pre>{JSON.stringify(query.data, null, 2)}</pre>
}
export function App() {
return <QueryClientProvider client={queryClient}><Todos /></QueryClientProvider>
}A query starts with cached initial data and uses a timestamp to represent when that data was last updated.
A server-rendered page already has the record needed by a query.
A list query contains a preview of an item needed by a detail query.
Seed data came from a source with a known modification time.
initialData populates the query cache when the query has not yet been created or cached. Unlike temporary placeholder content, it is persisted as the query's cached data.
Follow-up: How can cached source data be aged accurately? Pass the source query's dataUpdatedAt value as initialDataUpdatedAt, rather than inventing a freshness duration.
The option accepts either data directly or a function. A function is invoked once during shared/root query initialization and must synchronously return the initial value.
Follow-up: Why is the one-time behavior useful? It avoids repeatedly computing the seed during observer initialization while allowing lazy construction of the initial value.
Initial data is stale by default unless staleTime is configured. With the default zero stale time, a query can refetch immediately when it mounts.
Follow-up: When should initialDataUpdatedAt be preferred? Use it when the seed came from another query or source whose actual update timestamp is known.
placeholderDatastaleTimequeryClient.setQueryDataqueryClient.prefetchQuerydataUpdatedAtuseQuery