Overview
The QueriesObserver allows you to observe multiple queries at once and optionally combine their results. Itβs the foundation for framework-specific hooks like useQueries in React.
Constructor
const observer = new QueriesObserver < TCombinedResult >(
client : QueryClient ,
queries : Array < QueryObserverOptions > ,
options ?: QueriesObserverOptions < TCombinedResult >
)
queries
Array<QueryObserverOptions>
required
Array of query options
options
QueriesObserverOptions<TCombinedResult>
combine
(results: Array<QueryObserverResult>) => TCombinedResult
Function to combine results from all queries into a single value
Example:
const observer = new QueriesObserver ( queryClient , [
{
queryKey: [ 'todos' ],
queryFn: fetchTodos ,
},
{
queryKey: [ 'users' ],
queryFn: fetchUsers ,
},
])
Methods
subscribe()
Subscribes to updates from all queries.
const unsubscribe = observer . subscribe (
listener : ( results : Array < QueryObserverResult >) => void
): () => void
listener
(results: Array<QueryObserverResult>) => void
required
Callback function that receives an array of query results
Returns: Function to unsubscribe
Example:
const unsubscribe = observer . subscribe (( results ) => {
const [ todosResult , usersResult ] = results
console . log ( 'Todos:' , todosResult . data )
console . log ( 'Users:' , usersResult . data )
// Check if all queries are loaded
const allLoaded = results . every ( result => result . isSuccess )
console . log ( 'All loaded:' , allLoaded )
})
// Later, unsubscribe
unsubscribe ()
getCurrentResult()
Returns the current results from all queries without subscribing.
const results = observer . getCurrentResult (): Array < QueryObserverResult >
Returns: Array of current query results
Example:
const results = observer . getCurrentResult ()
const isAnyLoading = results . some ( result => result . isLoading )
const allSuccess = results . every ( result => result . isSuccess )
setQueries()
Updates the queries being observed.
observer . setQueries (
queries : Array < QueryObserverOptions > ,
options ?: QueriesObserverOptions < TCombinedResult >
): void
queries
Array<QueryObserverOptions>
required
New array of query options
options
QueriesObserverOptions<TCombinedResult>
New observer options
Example:
observer . setQueries ([
{
queryKey: [ 'todos' ],
queryFn: fetchTodos ,
staleTime: 10000 , // Updated option
},
{
queryKey: [ 'users' ],
queryFn: fetchUsers ,
},
{
queryKey: [ 'posts' ], // New query added
queryFn: fetchPosts ,
},
])
getQueries()
Returns the underlying Query instances.
const queries = observer . getQueries (): Array < Query >
Returns: Array of Query instances
getObservers()
Returns the underlying QueryObserver instances.
const observers = observer . getObservers (): Array < QueryObserver >
Returns: Array of QueryObserver instances
getOptimisticResult()
Returns optimistic results and a combine function.
const [ rawResults , combineResults , trackResults ] = observer . getOptimisticResult (
queries : Array < QueryObserverOptions > ,
combine ?: ( results : Array < QueryObserverResult >) => TCombinedResult
): [
rawResult : Array < QueryObserverResult > ,
combineResult : ( r ?: Array < QueryObserverResult >) => TCombinedResult ,
trackResult : () => Array < QueryObserverResult >
]
Returns: Tuple of [rawResults, combineFunction, trackFunction]
destroy()
Destroys the observer and cleans up all query observers.
Example:
Combining Results
You can provide a combine function to transform the array of results into any shape:
const observer = new QueriesObserver (
queryClient ,
[
{ queryKey: [ 'todos' ], queryFn: fetchTodos },
{ queryKey: [ 'users' ], queryFn: fetchUsers },
],
{
combine : ( results ) => {
return {
data: {
todos: results [ 0 ]. data ,
users: results [ 1 ]. data ,
},
isLoading: results . some ( r => r . isLoading ),
isError: results . some ( r => r . isError ),
}
},
}
)
Type Parameters
TCombinedResult - The type of the combined result (defaults to Array<QueryObserverResult>)
Usage Example
import { QueryClient , QueriesObserver } from '@tanstack/query-core'
const queryClient = new QueryClient ()
const observer = new QueriesObserver (
queryClient ,
[
{
queryKey: [ 'todos' ],
queryFn : async () => {
const response = await fetch ( '/api/todos' )
return response . json ()
},
},
{
queryKey: [ 'users' ],
queryFn : async () => {
const response = await fetch ( '/api/users' )
return response . json ()
},
},
],
{
combine : ( results ) => ({
todos: results [ 0 ]. data ,
users: results [ 1 ]. data ,
isPending: results . some ( r => r . isPending ),
}),
}
)
// Subscribe to updates
const unsubscribe = observer . subscribe (( results ) => {
const [ todosResult , usersResult ] = results
if ( todosResult . isSuccess && usersResult . isSuccess ) {
console . log ( 'Todos:' , todosResult . data )
console . log ( 'Users:' , usersResult . data )
}
})
// Later, clean up
unsubscribe ()
observer . destroy ()
Dynamic Queries
You can dynamically add or remove queries:
const observer = new QueriesObserver ( queryClient , [])
// Start with no queries
let queries = []
// Add a query
queries . push ({
queryKey: [ 'todos' ],
queryFn: fetchTodos ,
})
observer . setQueries ( queries )
// Add another query
queries . push ({
queryKey: [ 'users' ],
queryFn: fetchUsers ,
})
observer . setQueries ( queries )
// Remove a query
queries = queries . filter ( q => q . queryKey [ 0 ] !== 'todos' )
observer . setQueries ( queries )
Result Array Structure
The results array maintains the same order as the queries array:
const observer = new QueriesObserver ( queryClient , [
{ queryKey: [ 'todos' ], queryFn: fetchTodos }, // results[0]
{ queryKey: [ 'users' ], queryFn: fetchUsers }, // results[1]
{ queryKey: [ 'posts' ], queryFn: fetchPosts }, // results[2]
])
const results = observer . getCurrentResult ()
const todosData = results [ 0 ]. data
const usersData = results [ 1 ]. data
const postsData = results [ 2 ]. data
When using the combine option, the combined result is memoized and only recomputed when the individual query results change.