# Queries
Fetching data involves executing **query** operations using standard GraphQL documents. You can learn more about queries and GraphQL documents [here](https://graphql.org/learn/queries/) and [practice running queries in the playground](https://www.apollographql.com/docs/react/development-testing/developer-tooling/#features).
## Executing a query
### GraphQL document
Let's take this example GraphQL document throughout this section:
```graphql
query getUsers {
users {
id
firstname
lastname
email
}
}
```
::: tip
It is recommended to give a name to your GraphQL operations (here `getUsers`), so it is easier to find them in the Apollo Client devtools.
:::
This query would return a `data` object with an array of `users` with their `id`, `firstname`, `lastname` and `email`. It could look like this:
```json
{
"data": {
"users": [
{
"id": "abc",
"firstname": "James",
"lastname": "Holden",
"email": "james.holden@roci.com"
},
{
"id": "def",
"firstname": "Naomi",
"lastname": "Nagata",
"email": "naomi.nagata@roci.com"
}
]
}
}
```
You may ask: why is there a nested `users` property on `data`? Why isn't the array directly on `data`?
This is because you can select multiple root fields in a GraphQL operation:
```graphql
query getCatsAndDogs {
cats {
id
}
dogs {
id
}
}
```
In this case, the result could look like this:
```json
{
"data": {
"cats": [
{ "id": "abc" },
{ "id": "def" }
],
"dogs": [
{ "id": "ghi" },
{ "id": "jkl" }
]
}
}
```
There can also be other optional properties on the result alongside `data`:
- `errors` : an array of errors returned by the server
- `extensions` : additional informations such as execution timings
### useQuery
The main composition function used to execute queries is `useQuery`. In your component, start by importing it:
```vue
```
You can use `useQuery` in your `setup` option and pass it a GraphQL document as the first parameter. Then retrieve the query `result`:
```vue{3,7-16}
```
Note that `result` here is a `Ref` holding the data from the result returned by Apollo.
If you want to directly access the data object, use `result.value`:
```vue{2,19-21}
```
In this example, you could also watch the `Ref` directly:
```vue{19-20}
```
Let's expose our result in the template:
```vue{18-20,25-31}
{{ user.firstname }} {{ user.lastname }}
```
Beware that `result` may not contain your data at all time! It will initially be `undefined` until the query successfully completes. So it's a good idea to add a conditionnal before rendering the data:
```vue{2}
{{ user.firstname }} {{ user.lastname }}
```
## Query status
### Loading state
Alongside `result`, `useQuery` returns `loading`, a boolean `Ref` tracking the loading state of the query:
```vue{7,20,27,29}
Loading...
{{ user.firstname }} {{ user.lastname }}
```
### Error
There is also an `error` `Ref` that holds any error that may occur during the request:
```vue{7,21,30}
Loading...
Error: {{ error.message }}
{{ user.firstname }} {{ user.lastname }}
```
## useResult
The sister composition function `useResult` is available alongside `userQuery` to facilitate usage of the query `result`.
### Result picking
The first useful feature of `useResult` is picking one object from the result data. To do so, pass the `result` data as the first parameter, and a picking function as the third parameter:
```vue{2,18,21,34,35}
Loading...
Error: {{ error.message }}
{{ user.firstname }} {{ user.lastname }}
```
This is very useful if the data relevant to your component is nested in the query:
```js
const { result } = useQuery(gql`
query getMessages {
currentUser {
messages {
id
text
}
}
}
`)
const messages = useResult(result, null, data => data.currentUser.messages)
```
Another perk of `useResult` is that the picking function will silence errors inside the picking function. For example, if `result.value` is `undefined`, you don't have to add additional checks:
```js
// You don't need to do this!
const messages = useResult(result, null, data => data && data.currentUser && data.currentUser.messages)
// Instead do this:
const messages = useResult(result, null, data => data.currentUser.messages)
```
::: tip
Don't forget that `messages.value` can still be `null` until the query successfully completes!
:::
Another use case where `useResult` proves to be very useful is when you have multiple objects on the result data:
```js
const { result } = useQuery(gql`
query getUsersAndPosts {
users {
id
email
}
posts {
id
title
}
}
`)
const users = useResult(result, null, data => data.users)
const posts = useResult(result, null, data => data.posts)
```
Look how we cleanly separated the result data into two different `Ref`!
### Automatic picking
If there is only one object in the data, `useResult` will automatically try to pick the object:
```js{12}
const { result, loading } = useQuery(gql`
query getUsers {
users {
id
firstname
lastname
email
}
}
`)
const users = useResult(result)
```
Here `users.value` will be the `users` array retrieved from our server.
### Default value
Let's say we want to sort our users on their last names:
```vue{2,19-21,24,34,35}
Loading...
{{ user.firstname }} {{ user.lastname }}
```
Here we will run into an error because `result.value` can be `undefined` (and potentially `result.value.users` can also be `undefined`). So the `sort` method will throw an error when called in our `computed` property.
We could add checks, but it can rapidly become tedious:
```js
const sortedUsers = computed(() => result.value && result.value.users ? result.value.users.sort(
(a, b) => a.lastname.localeCompare(b.lastname)
) : [])
```
We can further simplify this with `useResult`:
```js{1,3,5}
const users = useResult(result) // Automatically picked
const sortedUsers = computed(() => users.value ? users.value.sort(
(a, b) => a.lastname.localeCompare(b.lastname)
) : [])
```
But we can eliminate the conditional entirely if we pass a default value as the 2nd parameter of `useResult`:
```js{1,3,5}
const users = useResult(result, []) // Defaults to an empty array
const sortedUsers = computed(() => users.value.sort(
(a, b) => a.lastname.localeCompare(b.lastname)
))
```
This is even more useful if we want to use the `users` array `Ref` in multiple places in our `setup` function!
## Variables
You can pass a `variables` object to the 2nd parameter of `useQuery`:
```js
const { result } = userQuery(gql`
query getUserById ($id: ID!) {
user (id: $id) {
id
email
}
}
`, {
id: 'abc-abc-abc',
})
```
### Variables Ref
You can change them later by retrieving their `variables` `Ref`:
```js{1,12-16}
const { result, variables } = userQuery(gql`
query getUserById ($id: ID!) {
user (id: $id) {
id
email
}
}
`, {
id: 'abc-abc-abc',
})
function selectUser (id) {
variables.value = {
id,
}
}
```
Alternatively, you can pass a `Ref` directly:
```js
import { ref } from '@vue/composition-api'
```
```js{1-3,12}
const variables = ref({
id: 'abc-abc-abc',
})
const { result } = userQuery(gql`
query getUserById ($id: ID!) {
user (id: $id) {
id
email
}
}
`, variables)
function selectUser (id) {
variables.value = {
id,
}
}
```
### Reactive object
You can also pass a reactive object:
```js
import { reactive } from '@vue/composition-api'
```
```js{1,15}
const variables = reactive({
id: 'abc-abc-abc',
})
const { result } = userQuery(gql`
query getUserById ($id: ID!) {
user (id: $id) {
id
email
}
}
`, variables)
function selectUser (id) {
variables.id = id
}
```
This also means you can pass `props` from `setup` directly, since `props` is already a reactive object:
```js
export default {
props: ['id'],
setup (props) {
const { result } = userQuery(gql`
query getUserById ($id: ID!) {
user (id: $id) {
id
email
}
}
`, props)
return {
result,
}
},
}
```
But beware if you add new props that aren't used in the GraphQL document, you will run into GraphQL validation errors!
### Variables function
Finally, you can pass variables as a function returning an object:
```js{12-14}
export default {
props: ['id'],
setup (props) {
const { result } = userQuery(gql`
query getUserById ($id: ID!) {
user (id: $id) {
id
email
}
}
`, () => ({
id: props.id,
}))
return {
result,
}
},
}
```
This variables function will be made reactive automatically, so whenever `props.id` changes, the `variables` object of the query will be updated.
This syntax is also useful if you want to use some `Ref`s in the `variables`:
```js
const id = ref('abc-abc-abc')
const { result } = userQuery(gql`
query getUserById ($id: ID!) {
user (id: $id) {
id
email
}
}
`, () => ({
id: id.value
}))
function selectUser (id) {
id.value = id
}
```
## Options
The third parameter of `useQuery` is an options object, used to configure your query.
Like `variables`, you can pass a `Ref`, a reactive object or a function that will automatically be reactive.
Using a `Ref`:
```js
const options = ref({
fetchPolicy: 'cache-first',
})
const { result } = useQuery(gql`
query getUsers {
users {
id
email
}
}
`, null, options)
```
Using a reactive object:
```js
const options = reactive({
fetchPolicy: 'cache-first',
})
const { result } = useQuery(gql`
query getUsers {
users {
id
email
}
}
`, null, options)
```
Using a function that will automatically be reactive:
```js
const fetchPolicy = ref('cache-first')
const { result } = useQuery(gql`
query getUsers {
users {
id
email
}
}
`, null, () => ({
fetchPolicy: fetchPolicy.value
}))
```
See the [API Reference](../api/use-query) for all the possible options.
### Disable a query
You can disable and re-enable a query with the `enabled` option:
```js
const enabled = ref(false)
const { result } = useQuery(gql`
...
`, null, () => ({
enabled: enabled.value,
}))
function enableQuery () {
enabled.value = true
}
```
### Fetch Policy
The `fetchPolicy` option allows you to customize how the query will use the Apollo Client cache.
```js
const { result } = useQuery(gql`
...
`, null, {
fetchPolicy: 'cache-and-network',
})
```
Available values are:
- `cache-first` (default): return result from cache. Only fetch from network if cached result is not available.
- `cache-and-network`: return result from cache first (if it exists), then return network result once it's available.
- `cache-only`: return result from cache if available, fail otherwise.
- `network-only`: return result from network, fail if network call doesn't succeed, save to cache.
- `no-cache`: return result from network, fail if network call doesn't succeed, don't save to cache.
## Updating cached results
When a query is completed, it will update the cache with the result data (depending on the [fetch policy](#fetch-policy)). This improves performance the next time the data needs to be rendered in your application and ensures that all components relying on a piece of data is always consistent.
However, you sometimes want to make sure that this data is up-to-date compared to the server.
### Polling
Polling means repeatedly calling the server to automatically update the query data.
You can enable polling with the `pollInterval` which will be the interval in ms between each requests repeatedly made to the server.
In this example, we will poll the server every second:
```js
const { result } = useQuery(gql`
...
`, null, {
pollInterval: 1000,
})
```
### Refetching
The other way is manually executing the query again in response to an event, as opposed to using a fixed interval.
This is done using the `refetch` function:
```vue{7,24,40}
Loading...
Error: {{ error.message }}
{{ user.firstname }} {{ user.lastname }}
```
## Event hooks
`useQuery` returns event hooks allowing you to execute code when a specific event occurs.
### onResult
This is called whenever a new result is available.
```js
const { onResult } = useQuery(...)
onResult(queryResult => {
console.log(queryResult.data)
console.log(queryResult.loading)
console.log(queryResult.networkStatus)
console.log(queryResult.stale)
})
```
You can pass the `notifyOnNetworkStatusChange` option to force the query to trigger a new resutl when the network status or error is updated:
```js
useQuery(gql`
...
`, null, {
notifyOnNetworkStatusChange: true,
})
```
### onError
It is triggered when an error occurs:
```js
const { onError } = useQuery(...)
onError(error => {
console.log(error.graphQLErrors)
console.log(error.networkError)
})
```
You can use the `logErrorMessages` function from the `@vue/apollo-util` package to format the error in the browser console:
```js
import { logErrorMessages } from '@vue/apollo-util'
const { onError } = useQuery(...)
onError(error => {
logErrorMessages(error)
})
```
Example error:

If you are using Webpack or Vue CLI, it's a good idea to only use it in development:
```js
import { logErrorMessages } from '@vue/apollo-util'
const { onError } = useQuery(...)
onError(error => {
if (process.env.NODE_ENV !== 'production') {
logErrorMessages(error)
}
})
```
That way it will be dropped when compiling the project for production.