A query function can be literally any function that returns a promise. The promise that is returned should either resolve the data or throw an error.
All of the following are valid query function configurations:
1useQuery({ queryKey: ['todos'], queryFn: fetchAllTodos })
2useQuery({ queryKey: ['todos', todoId], queryFn: () => fetchTodoById(todoId) })
3useQuery({
4 queryKey: ['todos', todoId],
5 queryFn: async () => {
6 const data = await fetchTodoById(todoId)
7 return data
8 },
9})
10useQuery({
11 queryKey: ['todos', todoId],
12 queryFn: ({ queryKey }) => fetchTodoById(queryKey[1]),
13})
Handling and Throwing Errors #
For TanStack Query to determine a query has errored, the query function must throw or return a rejected Promise. Any error that is thrown in the query function will be persisted on the error
state of the query.
1const { error } = useQuery({
2 queryKey: ['todos', todoId],
3 queryFn: async () => {
4 if (somethingGoesWrong) {
5 throw new Error('Oh no!')
6 }
7 if (somethingElseGoesWrong) {
8 return Promise.reject(new Error('Oh no!'))
9 }
10
11 return data
12 },
13})
Usage with fetch
and other clients that do not throw by default #
While most utilities like axios
or graphql-request
automatically throw errors for unsuccessful HTTP calls, some utilities like fetch
do not throw errors by default. If that's the case, you'll need to throw them on your own. Here is a simple way to do that with the popular fetch
API:
1useQuery({
2 queryKey: ['todos', todoId],
3 queryFn: async () => {
4 const response = await fetch('/todos/' + todoId)
5 if (!response.ok) {
6 throw new Error('Network response was not ok')
7 }
8 return response.json()
9 },
10})
Query Function Variables #
Query keys are not just for uniquely identifying the data you are fetching, but are also conveniently passed into your query function as part of the QueryFunctionContext. While not always necessary, this makes it possible to extract your query functions if needed:
1function Todos({ status, page }) {
2 const result = useQuery({
3 queryKey: ['todos', { status, page }],
4 queryFn: fetchTodoList,
5 })
6}
7
8// Access the key, status and page variables in your query function!
9function fetchTodoList({ queryKey }) {
10 const [_key, { status, page }] = queryKey
11 return new Promise()
12}
QueryFunctionContext #
The QueryFunctionContext
is the object passed to each query function. It consists of:
queryKey: QueryKey
: Query Keyssignal?: AbortSignal
- AbortSignal instance provided by TanStack Query
- Can be used for Query Cancellation
meta: Record<string, unknown> | undefined
- an optional field you can fill with additional information about your query
Additionally, Infinite Queries get the following options passed:
pageParam: TPageParam
- the page parameter used to fetch the current page
direction: 'forward' | 'backward'
- deprecated
- the direction of the current page fetch
- To get access to the direction of the current page fetch, please add a direction to
pageParam
fromgetNextPageParam
andgetPreviousPageParam
.