Queries
A query is a declarative dependency on an asynchronous source of data that is tied to a unique key. A query can be used with any Promise based method (including GET and POST methods) to fetch data from a server. If your method modifies data on the server, we recommend using Mutations instead.
To subscribe to a query in your components or custom hooks, call the useQuery hook with at least:
- A
unique keyfor the query. - A function that returns a promise that:
- Resolves the data or that throws an error.
The unique key you provide is used internally for refetching, caching, and sharing your queries throughout your application.
The query results returned by useQuery contains all the information about the query that you'll need for templating and any other usage of the data:
const result = useQuery("todos", fetchTodoList);
The result object contains a few very important states you'll need to be aware of to be productive. A query can only be in one of the following states at any given moment:
isLoadingorstatus === 'loading'- The query has no data and is currently fetching.isErrororstatus === 'error'- The query encountered an error.isSuccessorstatus === success- The query was successful and the data is available.isIdleorstatus === idle- The query is currently disabled. ( You`ll learn more about this in a bit. ).
Beyond those primary states, more information is available depending on the state of the query:
error- If the query is in anisErrorstate, the error is available via theerrorproperty.data- If the query is in asuccessstate, the data is available via thedataproperty.isFetching- In any state, if the query is fetching at any time (including background refetching)isFetchingwill betrue.
TIP
Every property of the result object is wrapped into a ref, so it can be safely destructured while retaining reactivity.
For most queries, it's usually sufficient to check for the isLoading state, then the isError state, then finally, assume that the data is available and render the successful state:
<script setup>
import { useQuery } from "vue-query";
function useTodosQuery() {
return useQuery("todos", fetchTodoList);
}
const { isLoading, isError, data, error } = useTodosQuery();
</script>
<template>
<span v-if="isLoading">Loading...</span>
<span v-else-if="isError">Error: {{ error.message }}</span>
<!-- We can assume by this point that `isSuccess === true` -->
<ul v-else>
<li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>
</ul>
</template>
If booleans aren't your thing, you can always use the status state as well:
<script setup>
import { useQuery } from "vue-query";
function useTodosQuery() {
return useQuery("todos", fetchTodoList);
}
const { status, data, error } = useTodosQuery();
</script>
<template>
<span v-if="status === 'loading'">Loading...</span>
<span v-else-if="status === 'error'">Error: {{ error.message }}</span>
<!-- also status === 'success', but "else" logic works, too -->
<ul v-else>
<li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>
</ul>
</template>
FetchStatus
In addition to the status property in the result object, you will also get an additional fetchStatus property with the following options:
fetchStatus === 'fetching'- The query is currently fetching.fetchStatus === 'paused'- The query wanted to fetch, but it is paused. Read more about this in the Network Mode guide.fetchStatus === 'idle'- The query is not doing anything at the moment.
Why two different states?
Background refetches and stale-while-revalidate logic make all combinations for status and fetchStatus possible. For example:
A query in
successstatus will usually be inidlefetchStatus, but it could also be infetchingif a background refetch is happening.A query that mounts and has no data will usually be in
loadingstatus andfetchingfetchStatus, but it could also bepausedif there is no network connection.
So keep in mind that a query can be in loading state without actually fetching data. As a rule of thumb:
The
statusgives information about the data - Do we have any data or not?The
fetchStatusgives information about thequeryFn- Is it running or not?
Vue Query