Fetch and cache data with the createQuery primitive. It returns a reactive query result that automatically updates when dependencies change in SolidJS.
Signature
function createQuery < TQueryFnData , TError , TData , TQueryKey >(
options : Accessor < CreateQueryOptions < TQueryFnData , TError , TData , TQueryKey >>,
queryClient ?: Accessor < QueryClient >,
) : CreateQueryResult < TData , TError >
Parameters
options
Accessor<CreateQueryOptions<TQueryFnData, TError, TData, TQueryKey>>
required
A Solid accessor (function) returning query configuration options. Unique identifier for the query. When used in an accessor, changes trigger refetch.
queryFn
QueryFunction<TQueryFnData, TQueryKey>
required
Function that fetches the data.
Set to false to disable automatic query execution.
Time in milliseconds until cached data is considered stale.
Time in milliseconds before unused data is garbage collected.
Interval in milliseconds for automatic refetching.
Refetch when window regains focus.
Refetch when network reconnects.
Number of retry attempts or boolean to enable/disable retries.
select
(data: TQueryData) => TData
Transform or select a part of the data.
Initial data to use before the query executes.
Placeholder data while the query is loading.
Accessor returning a custom QueryClient instance. If not provided, uses the client from context.
Returns
CreateQueryResult<TData, TError>
Reactive query state that updates automatically. The query result data. Returns undefined if not yet loaded.
The error object if the query failed.
true when fetching for the first time (no cached data).
true whenever the query is fetching (including background refetches).
true when the query has successfully fetched data.
true when the query encountered an error.
true when the query is pending (no data and no error yet).
status
'pending' | 'error' | 'success'
The current status of the query.
fetchStatus
'fetching' | 'paused' | 'idle'
The fetch status of the query.
refetch
() => Promise<QueryObserverResult>
Manually trigger a refetch of the query.
Type Parameters
TQueryFnData - Type returned by the query function
TError - Type of error (defaults to DefaultError)
TData - Type of data returned (defaults to TQueryFnData)
TQueryKey - Type of the query key (defaults to QueryKey)
Examples
Basic Usage
import { createQuery } from '@tanstack/solid-query'
import { For , Show } from 'solid-js'
function TodoList () {
const query = createQuery (() => ({
queryKey: [ 'todos' ],
queryFn : async () => {
const res = await fetch ( '/api/todos' )
return res . json ()
},
}))
return (
< div >
< Show when = { query . isLoading } >
< div > Loading... </ div >
</ Show >
< Show when = { query . error } >
< div > Error: { query . error . message } </ div >
</ Show >
< Show when = { query . data } >
< ul >
< For each = { query . data } >
{ ( todo ) => < li > { todo . title } </ li > }
</ For >
</ ul >
</ Show >
</ div >
)
}
Reactive Query Keys
import { createSignal } from 'solid-js'
import { createQuery } from '@tanstack/solid-query'
function TodoDetail () {
const [ todoId , setTodoId ] = createSignal ( 1 )
// Query automatically refetches when todoId changes
const query = createQuery (() => ({
queryKey: [ 'todo' , todoId ()],
queryFn : async () => {
const res = await fetch ( `/api/todos/ ${ todoId () } ` )
return res . json ()
},
}))
return (
< div >
< button onClick = { () => setTodoId ( id => id + 1 ) } >
Next Todo
</ button >
< Show when = { query . data } >
< h2 > { query . data . title } </ h2 >
</ Show >
</ div >
)
}
With TypeScript
import { createQuery } from '@tanstack/solid-query'
interface Todo {
id : number
title : string
completed : boolean
}
function TodoList () {
const query = createQuery (() => ({
queryKey: [ 'todos' ],
queryFn : async () : Promise < Todo []> => {
const res = await fetch ( '/api/todos' )
return res . json ()
},
}))
// query.data is typed as Todo[] | undefined
return < div > { /* ... */ } </ div >
}
Conditional Fetching
import { createSignal } from 'solid-js'
import { createQuery } from '@tanstack/solid-query'
function UserProfile () {
const [ userId , setUserId ] = createSignal < number | null >( null )
const query = createQuery (() => ({
queryKey: [ 'user' , userId ()],
queryFn : () => fetchUser ( userId () ! ),
enabled: userId () !== null , // Only fetch when userId is set
}))
return < div > { /* ... */ } </ div >
}
With Select
import { createQuery } from '@tanstack/solid-query'
function IncompleteTodos () {
const query = createQuery (() => ({
queryKey: [ 'todos' ],
queryFn: fetchTodos ,
select : ( todos ) => todos . filter ( todo => ! todo . completed ),
}))
// query.data only contains incomplete todos
return < div > { /* ... */ } </ div >
}
Dependent Queries
import { createQuery } from '@tanstack/solid-query'
function UserProjects () {
// First query
const userQuery = createQuery (() => ({
queryKey: [ 'user' ],
queryFn: fetchUser ,
}))
// Second query depends on first
const projectsQuery = createQuery (() => ({
queryKey: [ 'projects' , userQuery . data ?. id ],
queryFn : () => fetchProjects ( userQuery . data ! . id ),
enabled: !! userQuery . data ?. id ,
}))
return < div > { /* ... */ } </ div >
}
Initial Data
import { createQuery } from '@tanstack/solid-query'
function TodoDetail ( props : { todoId : number ; initialTodo ?: Todo }) {
const query = createQuery (() => ({
queryKey: [ 'todo' , props . todoId ],
queryFn : () => fetchTodo ( props . todoId ),
initialData: props . initialTodo ,
}))
// query.data starts with initialTodo if provided
return < div > { /* ... */ } </ div >
}
Polling/Refetch Interval
import { createQuery } from '@tanstack/solid-query'
function RealtimeData () {
const query = createQuery (() => ({
queryKey: [ 'realtime-data' ],
queryFn: fetchRealtimeData ,
refetchInterval: 5000 , // Refetch every 5 seconds
}))
return < div > { /* ... */ } </ div >
}
Manual Refetch
import { createQuery } from '@tanstack/solid-query'
function ManualRefetch () {
const query = createQuery (() => ({
queryKey: [ 'data' ],
queryFn: fetchData ,
}))
return (
< div >
< button onClick = { () => query . refetch () } >
Refresh Data
</ button >
< Show when = { query . data } >
< pre > { JSON . stringify ( query . data , null , 2 ) } </ pre >
</ Show >
</ div >
)
}
Error Handling
import { createQuery } from '@tanstack/solid-query'
import { Show } from 'solid-js'
function ErrorHandling () {
const query = createQuery (() => ({
queryKey: [ 'data' ],
queryFn: fetchData ,
retry: 3 ,
retryDelay : ( attemptIndex ) => Math . min ( 1000 * 2 ** attemptIndex , 30000 ),
}))
return (
< Show
when = { ! query . isError }
fallback = {
< div >
< p > Error: { query . error ?. message } </ p >
< button onClick = { () => query . refetch () } > Try Again </ button >
</ div >
}
>
{ /* Success content */ }
</ Show >
)
}
Notes
The options parameter must be an accessor (function). This allows SolidJS to track dependencies and automatically refetch when reactive values change.
Use createMemo if you need to derive query options from multiple signals: const queryOptions = createMemo (() => ({
queryKey: [ 'data' , filter (), page ()],
queryFn : () => fetchData ( filter (), page ()),
}))
const query = createQuery ( queryOptions )