docs/framework/solid/reference/useQuery.md
const {
data,
dataUpdatedAt,
error,
errorUpdatedAt,
failureCount,
failureReason,
fetchStatus,
isError,
isFetched,
isFetchedAfterMount,
isFetching,
isInitialLoading,
isLoading,
isLoadingError,
isPaused,
isPending,
isPlaceholderData,
isRefetchError,
isRefetching,
isStale,
isSuccess,
refetch,
status,
} = useQuery(
() => ({
queryKey,
queryFn,
enabled,
select,
placeholderData,
deferStream,
reconcile,
gcTime,
networkMode,
initialData,
initialDataUpdatedAt,
meta,
queryKeyHashFn,
refetchInterval,
refetchIntervalInBackground,
refetchOnMount,
refetchOnReconnect,
refetchOnWindowFocus,
retry,
retryOnMount,
retryDelay,
staleTime,
throwOnError,
}),
() => queryClient,
)
Here are some examples of how to use the useQuery primitive in Solid Query.
The most basic usage of useQuery is to create a query that fetches data from an API.
import { useQuery } from '@tanstack/solid-query'
function App() {
const todos = useQuery(() => ({
queryKey: 'todos',
queryFn: async () => {
const response = await fetch('/api/todos')
if (!response.ok) {
throw new Error('Failed to fetch todos')
}
return response.json()
},
}))
return (
<div>
<Show when={todos.isError}>
<div>Error: {todos.error.message}</div>
</Show>
<Show when={todos.isLoading}>
<div>Loading...</div>
</Show>
<Show when={todos.isSuccess}>
<div>
<div>Todos:</div>
<ul>
<For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>
</ul>
</div>
</Show>
</div>
)
}
The reason why useQuery accepts a function that returns an object is to allow for reactive options. This is useful when query options depend on other values/signals that might change over time. Solid Query can track the passed function in a reactive scope and re-run it whenever the dependencies change.
import { useQuery } from '@tanstack/solid-query'
function App() {
const [filter, setFilter] = createSignal('all')
const todos = useQuery(() => ({
queryKey: ['todos', filter()],
queryFn: async () => {
const response = await fetch(`/api/todos?filter=${filter()}`)
if (!response.ok) {
throw new Error('Failed to fetch todos')
}
return response.json()
},
}))
return (
<div>
<div>
<button onClick={() => setFilter('all')}>All</button>
<button onClick={() => setFilter('active')}>Active</button>
<button onClick={() => setFilter('completed')}>Completed</button>
</div>
<Show when={todos.isError}>
<div>Error: {todos.error.message}</div>
</Show>
<Show when={todos.isLoading}>
<div>Loading...</div>
</Show>
<Show when={todos.isSuccess}>
<div>
<div>Todos:</div>
<ul>
<For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>
</ul>
</div>
</Show>
</div>
)
}
SuspenseuseQuery supports triggering SolidJS Suspense and ErrorBoundary components when the query is in a pending or error state. This allows you to easily handle loading and error states in your components.
import { useQuery } from '@tanstack/solid-query'
function App() {
const todos = useQuery(() => ({
queryKey: 'todos',
queryFn: async () => {
const response = await fetch('/api/todos')
if (!response.ok) {
throw new Error('Failed to fetch todos')
}
return response.json()
},
throwOnError: true,
}))
return (
<ErrorBoundary fallback={<div>Error: {todos.error.message}</div>}>
<Suspense fallback={<div>Loading...</div>}>
<div>
<div>Todos:</div>
<ul>
<For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>
</ul>
</div>
</Suspense>
</ErrorBoundary>
)
}
useQuery ParametersAccessor<QueryOptions>queryKey: unknown[]enabled is not set to false).queryFn: (context: QueryFunctionContext) => Promise<TData>undefined.enabled: booleanfalse to disable this query from automatically running.select: (data: TData) => unknowndata value, but does not affect what gets stored in the query cache.select function will only run if data changed, or if the reference to the select function itself changes. To optimize, wrap the function in useCallback.placeholderData: TData | (previousValue: TData | undefined; previousQuery: Query | undefined,) => TDatapending state.placeholderData is not persisted to the cacheplaceholderData, as a first argument you will receive previously watched query data if available, and the second argument will be the complete previousQuery instance.deferStream: booleanfalsedeferStream to true to wait for the query to resolve on the server before flushing the stream.reconcile: false | string | ((oldData: TData | undefined, newData: TData) => TData)falsegcTime: number | Infinity5 * 60 * 1000 (5 minutes) or Infinity during SSRInfinity, will disable garbage collectionnetworkMode: 'online' | 'always' | 'offlineFirst''online'initialData: TData | () => TDatastaleTime has been set.initialData is persisted to the cacheinitialDataUpdatedAt: number | (() => number | undefined)initialData itself was last updated.meta: Record<string, unknown>query is available, and is also part of the QueryFunctionContext provided to the queryFn.queryKeyHashFn: (queryKey: QueryKey) => stringqueryKey to a string.refetchInterval: number | false | ((query: Query) => number | false | undefined)refetchIntervalInBackground: booleantrue, queries that are set to continuously refetch with a refetchInterval will continue to refetch while their tab/window is in the backgroundrefetchOnMount: boolean | "always" | ((query: Query) => boolean | "always")truetrue, the query will refetch on mount if the data is stale.false, the query will not refetch on mount."always", the query will always refetch on mount.refetchOnWindowFocus: boolean | "always" | ((query: Query) => boolean | "always")truetrue, the query will refetch on window focus if the data is stale.false, the query will not refetch on window focus."always", the query will always refetch on window focus.refetchOnReconnect: boolean | "always" | ((query: Query) => boolean | "always")truetrue, the query will refetch on reconnect if the data is stale.false, the query will not refetch on reconnect."always", the query will always refetch on reconnect.retry: boolean | number | (failureCount: number, error: TError) => booleanfalse, failed queries will not retry by default.true, failed queries will retry infinitely.number, e.g. 3, failed queries will retry until the failed query count meets that number.3 on the client and 0 on the serverretryOnMount: booleanfalse, the query will not be retried on mount if it contains an error. Defaults to true.retryDelay: number | (retryAttempt: number, error: TError) => numberretryAttempt integer and the actual Error and returns the delay to apply before the next attempt in milliseconds.attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000) applies exponential backoff.attempt => attempt * 1000 applies linear backoff.staleTime: number | Infinity0Infinity, the data will never be considered stalethrowOnError: undefined | boolean | (error: TError, query: Query) => booleantrue if you want errors to be thrown in the render phase and propagate to the nearest error boundaryfalse to disable suspense's default behavior of throwing errors to the error boundary.true) or return the error as state (false)Accessor<QueryClient>useQuery Return Value - Store<QueryResult<TData, TError>>useQuery returns a SolidJS store with the following properties:
status: QueryStatuspending if there's no cached data and no query attempt was finished yet.error if the query attempt resulted in an error. The corresponding error property has the error received from the attempted fetchsuccess if the query has received a response with no errors and is ready to display its data. The corresponding data property on the query is the data received from the successful fetch or if the query's enabled property is set to false and has not been fetched yet data is the first initialData supplied to the query on initialization.isPending: booleanstatus variable above, provided for convenience.isSuccess: booleanstatus variable above, provided for convenience.isError: booleanstatus variable above, provided for convenience.isLoadingError: booleantrue if the query failed while fetching for the first time.isRefetchError: booleantrue if the query failed while refetching.data: Resource<TData>undefined.data property is a SolidJS resource. This means that if the data is accessed underneath a <Suspense> component,
it will trigger the Suspense boundary if the data is not available yet.dataUpdatedAt: numberstatus as "success".error: null | TErrornullerrorUpdatedAt: numberstatus as "error".isStale: booleantrue if the data in the cache is invalidated or if the data is older than the given staleTime.isPlaceholderData: booleantrue if the data shown is the placeholder data.isFetched: booleantrue if the query has been fetched.isFetchedAfterMount: booleantrue if the query has been fetched after the component mounted.fetchStatus: FetchStatusfetching: Is true whenever the queryFn is executing, which includes initial pending as well as background refetches.paused: The query wanted to fetch, but has been paused.idle: The query is not fetching.isFetching: booleanfetchStatus variable above, provided for convenience.isPaused: booleanfetchStatus variable above, provided for convenience.isRefetching: booleantrue whenever a background refetch is in-flight, which does not include initial pendingisFetching && !isPendingisLoading: booleantrue whenever the first fetch for a query is in-flightisFetching && isPendingisInitialLoading: booleanisLoading, will be removed in the next major version.failureCount: number0 when the query succeeds.failureReason: null | TErrornull when the query succeeds.errorUpdateCount: numberrefetch: (options: { throwOnError: boolean, cancelRefetch: boolean }) => Promise<UseQueryResult>throwOnError: true optioncancelRefetch?: boolean
true
false, no refetch will be made if there is already a request running.