Skip to main content

Query

The Query class represents a single query instance in the cache. It manages the lifecycle of a query, including fetching, caching, and state management.

Import

import { Query } from '@tanstack/query-core'

Constructor

class Query<
  TQueryFnData = unknown,
  TError = DefaultError,
  TData = TQueryFnData,
  TQueryKey extends QueryKey = QueryKey,
> {
  constructor(config: QueryConfig<TQueryFnData, TError, TData, TQueryKey>)
}

Type Parameters

TQueryFnData
type
default:"unknown"
The type of data returned by the query function
TError
type
default:"DefaultError"
The type of error that can be thrown
TData
type
default:"TQueryFnData"
The type of data after transformation
TQueryKey
type
default:"QueryKey"
The type of the query key

Properties

state

state: QueryState<TData, TError>
The current state of the query.
interface QueryState<TData = unknown, TError = DefaultError> {
  data: TData | undefined
  dataUpdateCount: number
  dataUpdatedAt: number
  error: TError | null
  errorUpdateCount: number
  errorUpdatedAt: number
  fetchFailureCount: number
  fetchFailureReason: TError | null
  fetchMeta: FetchMeta | null
  isInvalidated: boolean
  status: 'pending' | 'error' | 'success'
  fetchStatus: 'fetching' | 'paused' | 'idle'
}

queryKey

queryKey: TQueryKey
The unique key for this query.

queryHash

queryHash: string
A hashed version of the query key used for internal lookups.

options

options: QueryOptions<TQueryFnData, TError, TData, TQueryKey>
The query configuration options.

Methods

fetch

fetch(
  options?: QueryOptions<TQueryFnData, TError, TData, TQueryKey>,
  fetchOptions?: FetchOptions
): Promise<TData>
Fetch or refetch the query data.

cancel

cancel(options?: CancelOptions): Promise<void>
Cancel any ongoing query fetches.

invalidate

invalidate(): void
Mark the query as stale/invalidated.

setState

setState(
  state: QueryState<TData, TError>,
  options?: SetStateOptions
): void
Update the query state.

setData

setData(
  updater: Updater<TData | undefined, TData | undefined>,
  options?: SetDataOptions
): TData | undefined
Manually set the query data.

isStale

isStale(): boolean
Check if the query is stale based on staleTime.

isStaleByTime

isStaleByTime(staleTime?: number): boolean
Check if the query is stale based on a specific stale time.

destroy

destroy(): void
Clean up and remove the query.

Examples

Accessing Query State

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const queryCache = queryClient.getQueryCache()

// Get a specific query
const query = queryCache.find({ queryKey: ['posts'] })

if (query) {
  console.log('Query Key:', query.queryKey)
  console.log('Query Hash:', query.queryHash)
  console.log('Status:', query.state.status)
  console.log('Data:', query.state.data)
  console.log('Error:', query.state.error)
  console.log('Fetch Status:', query.state.fetchStatus)
  console.log('Is Stale:', query.isStale())
}

Finding Queries

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const queryCache = queryClient.getQueryCache()

// Get all queries
const allQueries = queryCache.getAll()

// Find queries by partial key
const postQueries = queryCache.findAll({ queryKey: ['posts'] })

// Find with predicate
const staleQueries = queryCache.findAll({
  predicate: (query) => query.isStale(),
})

console.log(`Total queries: ${allQueries.length}`)
console.log(`Post queries: ${postQueries.length}`)
console.log(`Stale queries: ${staleQueries.length}`)

Manually Invalidating Queries

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const query = queryClient.getQueryCache().find({ queryKey: ['posts'] })

if (query) {
  // Mark as stale
  query.invalidate()
  
  // Refetch if there are active observers
  query.fetch()
}

Setting Query Data Manually

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const query = queryClient.getQueryCache().find({ queryKey: ['post', 1] })

if (query) {
  // Set data directly
  query.setData({ id: 1, title: 'Updated Title' })
  
  // Or use an updater function
  query.setData((oldData) => ({
    ...oldData,
    title: 'Updated Title',
  }))
}

Checking Query Staleness

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const query = queryClient.getQueryCache().find({ queryKey: ['posts'] })

if (query) {
  // Check with default staleTime
  const isStale = query.isStale()
  
  // Check with custom staleTime (5 minutes)
  const isStaleByTime = query.isStaleByTime(5 * 60 * 1000)
  
  console.log('Is stale (default):', isStale)
  console.log('Is stale (5 min):', isStaleByTime)
}

Subscribing to Query Changes

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const queryCache = queryClient.getQueryCache()

// Subscribe to all query changes
const unsubscribe = queryCache.subscribe((event) => {
  console.log('Event type:', event.type)
  console.log('Query:', event.query.queryKey)
  console.log('Status:', event.query.state.status)
})

// Clean up
unsubscribe()

Canceling Queries

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()

// Cancel all queries
await queryClient.cancelQueries()

// Cancel specific queries
await queryClient.cancelQueries({ queryKey: ['posts'] })

// Or cancel directly on the query
const query = queryClient.getQueryCache().find({ queryKey: ['posts'] })
if (query) {
  await query.cancel()
}

Removing Queries

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const query = queryClient.getQueryCache().find({ queryKey: ['posts'] })

if (query) {
  // Remove the query from cache
  query.destroy()
  
  // Or use queryClient methods
  queryClient.removeQueries({ queryKey: ['posts'] })
}

Query Metadata

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const query = queryClient.getQueryCache().find({ queryKey: ['posts'] })

if (query) {
  console.log('Data Update Count:', query.state.dataUpdateCount)
  console.log('Data Updated At:', new Date(query.state.dataUpdatedAt))
  console.log('Error Update Count:', query.state.errorUpdateCount)
  console.log('Fetch Failure Count:', query.state.fetchFailureCount)
  console.log('Is Invalidated:', query.state.isInvalidated)
}

Fetching with Options

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const query = queryClient.getQueryCache().find({ queryKey: ['posts'] })

if (query) {
  // Fetch with custom options
  await query.fetch({
    queryFn: () => fetchPosts(),
    staleTime: 60 * 1000,
    gcTime: 5 * 60 * 1000,
  })
  
  // Fetch with meta information
  await query.fetch(undefined, {
    cancelRefetch: true,
    meta: { requestId: '123' },
  })
}

Query State

The query state object contains:
status
'pending' | 'error' | 'success'
The current status of the query
fetchStatus
'fetching' | 'paused' | 'idle'
The fetch status of the query
data
TData | undefined
The data returned by the query function
error
TError | null
The error thrown by the query function (only set on error)
dataUpdateCount
number
The number of times the data has been updated
dataUpdatedAt
number
Timestamp when data was last updated
errorUpdateCount
number
The number of times the query has errored
errorUpdatedAt
number
Timestamp when error was last updated
fetchFailureCount
number
The number of consecutive fetch failures
fetchFailureReason
TError | null
The reason for the last fetch failure
isInvalidated
boolean
Whether the query has been invalidated
fetchMeta
FetchMeta | null
Additional metadata about the fetch

Notes

  • Query is a low-level class typically created and managed by QueryCache
  • Each unique query key gets its own Query instance
  • Queries are kept in cache based on gcTime (garbage collection time)
  • The queryHash is used for efficient internal lookups
  • Queries support multiple concurrent observers (e.g., multiple components using the same query)
  • State changes trigger notifications to observers and cache subscribers
  • Queries automatically refetch based on staleTime and other configuration
  • The fetch() method is used internally by observers to trigger data fetching
  • Use QueryClient methods instead of directly manipulating queries in most cases

Build docs developers (and LLMs) love