The QueryObserver is the underlying mechanism that powers hooks like useQuery. It subscribes to a query and notifies listeners when the query state changes.
Constructor
Creates a new QueryObserver instance.
const observer = new QueryObserver < TQueryFnData , TError , TData , TQueryData , TQueryKey >(
client : QueryClient ,
options : QueryObserverOptions < TQueryFnData , TError , TData , TQueryData , TQueryKey >
)
The QueryClient instance to use.
options
QueryObserverOptions
required
Options for the observer. A unique key for the query.
The function that the query will use to request data.
enabled
boolean | ((query: Query) => boolean)
Whether the query should run automatically. Default is true.
staleTime
number | ((query: Query) => number)
Time in milliseconds after which data is considered stale.
Time in milliseconds that unused/inactive cache data remains in memory.
refetchOnMount
boolean | 'always' | ((query: Query) => boolean | 'always')
Whether to refetch on mount. Default is true.
refetchOnWindowFocus
boolean | 'always' | ((query: Query) => boolean | 'always')
Whether to refetch on window focus. Default is true.
refetchOnReconnect
boolean | 'always' | ((query: Query) => boolean | 'always')
Whether to refetch on reconnect. Default is true.
refetchInterval
number | false | ((query: Query) => number | false)
Interval in milliseconds to refetch the query.
refetchIntervalInBackground
Whether to continue refetch interval when window is not focused.
select
(data: TQueryData) => TData
Function to transform or select a part of the data.
placeholderData
TQueryData | ((previousValue: TQueryData | undefined, previousQuery: Query | undefined) => TQueryData)
Placeholder data to show while the query is loading.
notifyOnChangeProps
Array<keyof QueryObserverResult> | 'all' | (() => Array<keyof QueryObserverResult> | 'all')
Which properties should trigger re-renders.
Example
import { QueryObserver } from '@tanstack/query-core'
const observer = new QueryObserver ( queryClient , {
queryKey: [ 'todos' ],
queryFn: fetchTodos ,
staleTime: 5000 ,
})
Methods
subscribe
Subscribes to the observer and receives updates when the query state changes.
subscribe ( listener : ( result : QueryObserverResult < TData , TError >) => void ): () => void
listener
(result: QueryObserverResult<TData, TError>) => void
required
Function called when the query result changes.
Returns an unsubscribe function.
Example
const unsubscribe = observer . subscribe (( result ) => {
console . log ( 'Query result:' , result . data )
console . log ( 'Is loading:' , result . isLoading )
console . log ( 'Is error:' , result . isError )
})
// Later, unsubscribe
unsubscribe ()
setOptions
Updates the observer options. This will trigger a re-evaluation of the query.
setOptions (
options : QueryObserverOptions < TQueryFnData , TError , TData , TQueryData , TQueryKey >
): void
options
QueryObserverOptions
required
New options for the observer.
Example
observer . setOptions ({
queryKey: [ 'todos' ],
queryFn: fetchTodos ,
staleTime: 10000 , // Update staleTime
})
getCurrentResult
Returns the current result of the query.
getCurrentResult (): QueryObserverResult < TData , TError >
Returns the current query result. The data returned from the query.
The error object if the query failed.
status
'pending' | 'error' | 'success'
The status of the query.
fetchStatus
'fetching' | 'paused' | 'idle'
The fetch status of the query.
True if the query is in a loading state (pending + fetching).
True if the query is in a pending state.
True if the query encountered an error.
True if the query was successful.
True if the query is currently fetching.
True if the query is refetching.
True if the data is stale.
refetch
(options?: RefetchOptions) => Promise<QueryObserverResult>
Function to manually refetch the query.
Example
const result = observer . getCurrentResult ()
console . log ( result . data )
getCurrentQuery
Returns the current Query instance being observed.
getCurrentQuery (): Query < TQueryFnData , TError , TQueryData , TQueryKey >
Returns the Query instance.
getOptimisticResult
Returns an optimistic result based on the provided options without subscribing.
getOptimisticResult (
options : DefaultedQueryObserverOptions < TQueryFnData , TError , TData , TQueryData , TQueryKey >
): QueryObserverResult < TData , TError >
options
DefaultedQueryObserverOptions
required
Options to compute the optimistic result.
Returns an optimistic query result.
refetch
Manually refetches the query.
refetch ( options ?: RefetchOptions ): Promise < QueryObserverResult < TData , TError >>
Options for refetching. Whether to cancel any ongoing refetch. Default is true.
Promise<QueryObserverResult>
Returns a promise that resolves with the query result.
Example
const result = await observer . refetch ()
console . log ( 'Refetched data:' , result . data )
fetchOptimistic
Fetches the query with the provided options and returns the result.
fetchOptimistic (
options : QueryObserverOptions < TQueryFnData , TError , TData , TQueryData , TQueryKey >
): Promise < QueryObserverResult < TData , TError >>
options
QueryObserverOptions
required
Options for the fetch.
Promise<QueryObserverResult>
Returns a promise that resolves with the query result.
destroy
Destroys the observer and cleans up all subscriptions and timers.
Example
trackResult
Returns a proxied version of the result that tracks which properties are accessed.
trackResult (
result : QueryObserverResult < TData , TError > ,
onPropTracked ?: ( key : keyof QueryObserverResult ) => void
): QueryObserverResult < TData , TError >
result
QueryObserverResult
required
The result to track.
onPropTracked
(key: keyof QueryObserverResult) => void
Callback called when a property is accessed.
Returns a proxied result that tracks property access.
trackProp
Manually track a specific property.
trackProp ( key : keyof QueryObserverResult ): void
key
keyof QueryObserverResult
required
The property key to track.
Lifecycle
When you subscribe to a QueryObserver:
The observer adds itself to the query’s list of observers
If needed, the query will fetch data on mount
The observer sets up stale and refetch interval timers
When the query state changes, the observer notifies all listeners
When you unsubscribe, the observer cleans up timers and removes itself from the query
Usage Example
Here’s a complete example showing how to use QueryObserver:
import { QueryClient , QueryObserver } from '@tanstack/query-core'
// Create client
const queryClient = new QueryClient ()
// Create observer
const observer = new QueryObserver ( queryClient , {
queryKey: [ 'todos' ],
queryFn : async () => {
const response = await fetch ( '/api/todos' )
return response . json ()
},
staleTime: 5000 ,
})
// Subscribe to changes
const unsubscribe = observer . subscribe (( result ) => {
if ( result . isLoading ) {
console . log ( 'Loading...' )
} else if ( result . isError ) {
console . error ( 'Error:' , result . error )
} else if ( result . isSuccess ) {
console . log ( 'Data:' , result . data )
}
})
// Later, update options
observer . setOptions ({
queryKey: [ 'todos' ],
queryFn: fetchTodos ,
staleTime: 10000 ,
})
// Cleanup when done
unsubscribe ()
observer . destroy ()
Internal Methods
The following methods are used internally and are not typically needed:
shouldFetchOnReconnect
Determines if the query should refetch when reconnecting.
shouldFetchOnReconnect (): boolean
shouldFetchOnWindowFocus
Determines if the query should refetch when the window regains focus.
shouldFetchOnWindowFocus (): boolean
updateResult
Updates the current result and notifies listeners if changed.
protected updateResult (): void
onQueryUpdate
Called when the query is updated.