---
title: Queries
description: Fetch data with the useQuery hook
---

import { MultiCodeBlock } from 'gatsby-theme-apollo-docs';
import QueryOptions from '../../shared/query-options.mdx';
import QueryResult from '../../shared/query-result.mdx';

> This article was recently updated to reflect Apollo Client's support
> for React Hooks. To perform queries with Apollo Client's render-prop API instead,
> see the previous version of this article.

Fetching data in a simple, predictable way is one of the core features of Apollo Client. This article demonstrates how to fetch GraphQL data in React with the `useQuery` hook and attach the result to your UI. You'll also learn how Apollo Client simplifies data management code by tracking error and loading states for you.

## Prerequisites

This article assumes you're familiar with building basic GraphQL queries. If you need a refresher, we recommend that you [read this guide](http://graphql.org/learn/queries/) and [practice running queries in GraphiQL](../development-testing/developer-tooling/#features). Apollo Client queries are standard GraphQL, so any query that runs in GraphiQL will also run when provided to `useQuery`.

This article also assumes that you've already set up Apollo Client and have wrapped your React app in an `ApolloProvider` component. Read our [getting started guide](../get-started/) if you need help with either of those steps.

> To follow along with the examples below, open up our [starter project](https://codesandbox.io/s/j2ly83749w) and [sample GraphQL server](https://codesandbox.io/s/32ypr38l61) on CodeSandbox. You can view the completed version of the app [here](https://codesandbox.io/s/n3jykqpxwm).

## Executing a query

The `useQuery` [React hook](https://reactjs.org/docs/hooks-intro.html) is the primary API for executing queries in an Apollo application. To run a query within a React component, call `useQuery` and pass it a GraphQL query string. When your component renders, `useQuery` returns an object from Apollo Client that contains `loading`, `error`, and `data` properties you can use to render your UI.

Let's look at an example. First, we'll create a GraphQL query named `GET_DOGS`. Remember to wrap query strings in the `gql` function to parse them into query documents:

<MultiCodeBlock>
<div data-language="hooks-js">

```tsx:title=index.js
import { gql, useQuery } from '@apollo/client';

const GET_DOGS = gql`
  {
    dogs {
      id
      breed
    }
  }
`;
```

</div>
<div data-language="js">

```tsx:title=index.js
import { gql } from "@apollo/client";
import { Query } from '@apollo/react-components';

const GET_DOGS = gql`
  {
    dogs {
      id
      breed
    }
  }
`;
```

</div>
</MultiCodeBlock>

Next, we'll create a component named `Dogs`. Inside it, we'll pass our `GET_DOGS` query to the `useQuery` hook:

<MultiCodeBlock>
<div data-language="hooks-js">

```tsx:title=index.js
function Dogs({ onDogSelected }) {
  const { loading, error, data } = useQuery(GET_DOGS);

  if (loading) return 'Loading...';
  if (error) return `Error! ${error.message}`;

  return (
    <select name="dog" onChange={onDogSelected}>
      {data.dogs.map(dog => (
        <option key={dog.id} value={dog.breed}>
          {dog.breed}
        </option>
      ))}
    </select>
  );
}
```

</div>
<div data-language="js">

```tsx:title=index.js
const Dogs = ({ onDogSelected }) => (
  <Query query={GET_DOGS}>
    {({ loading, error, data }) => {
      if (loading) return 'Loading...';
      if (error) return `Error! ${error.message}`;

      return (
        <select name="dog" onChange={onDogSelected}>
          {data.dogs.map(dog => (
            <option key={dog.id} value={dog.breed}>
              {dog.breed}
            </option>
          ))}
        </select>
      );
    }}
  </Query>
);
```

</div>
</MultiCodeBlock>

As our query executes and the values of `loading`, `error`, and `data` change, the `Dogs` component can intelligently render different UI elements according to the query's state:

- As long as `loading` is `true` (indicating the query is still in flight), the component presents a `Loading...` notice.
- When loading is `false` and there is no `error`, the query has completed. The component renders a dropdown menu that's populated with the list of dog breeds returned by the server.

When the user selects a dog breed from the populated dropdown, the selection is sent to the parent component via the provided `onDogSelected` function.

In the next step, we'll associate the dropdown with a more sophisticated query that uses GraphQL variables.

## Caching query results

Whenever Apollo Client fetches query results from your server, it automatically **caches**
those results locally. This makes subsequent executions of the same query
extremely fast.

To see this caching in action, let's build a new component called `DogPhoto`. `DogPhoto` accepts a prop called `breed` that reflects the current value of the dropdown menu in our `Dogs` component:

<MultiCodeBlock>
<div data-language="hooks-js">

```jsx:title=index.js
const GET_DOG_PHOTO = gql`
  query Dog($breed: String!) {
    dog(breed: $breed) {
      id
      displayImage
    }
  }
`;

function DogPhoto({ breed }) {
  const { loading, error, data } = useQuery(GET_DOG_PHOTO, {
    variables: { breed },
  });

  if (loading) return null;
  if (error) return `Error! ${error}`;

  return (
    <img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
  );
}
```

</div>
<div data-language="js">

```jsx:title=index.js
const GET_DOG_PHOTO = gql`
  query Dog($breed: String!) {
    dog(breed: $breed) {
      id
      displayImage
    }
  }
`;

const DogPhoto = ({ breed }) => (
  <Query query={GET_DOG_PHOTO} variables={{ breed }}>
    {({ loading, error, data }) => {
      if (loading) return null;
      if (error) return `Error! ${error}`;

      return (
        <img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
      );
    }}
  </Query>
);
```

</div>
</MultiCodeBlock>

Notice that we're providing a configuration option (`variables`) to the `useQuery` hook this time. The `variables` option is an object that contains all of the variables we want to pass to our GraphQL query. In this case, we want to pass the currently selected breed from the dropdown.

Select `bulldog` from the dropdown to see its photo appear. Then switch to another breed, and then switch _back_ to `bulldog`. You'll notice that the bulldog photo loads instantly the second time around. This is the Apollo cache at work!

Next, let's learn some techniques for ensuring that our cached data is fresh.

## Updating cached query results

Caching query results is handy and easy to do, but sometimes you
want to make sure that cached data is up to date with your server. Apollo Client supports two strategies for this: **polling** and **refetching**.

### Polling

Polling provides near-real-time synchronization with your server by causing a query to execute periodically at a specified interval. To enable polling for a query, pass a `pollInterval` configuration option to the `useQuery` hook with an interval in milliseconds:

<MultiCodeBlock>
<div data-language="hooks-js">

```jsx:title=index.js
function DogPhoto({ breed }) {
  const { loading, error, data } = useQuery(GET_DOG_PHOTO, {
    variables: { breed },
    skip: !breed,
    pollInterval: 500,
  });

  if (loading) return null;
  if (error) return `Error! ${error}`;

  return (
    <img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
  );
}
```

</div>
<div data-language="js">

```jsx:title=index.js
const DogPhoto = ({ breed }) => (
  <Query
    query={GET_DOG_PHOTO}
    variables={{ breed }}
    skip={!breed}
    pollInterval={500}
  >
    {({ loading, error, data }) => {
      if (loading) return null;
      if (error) return `Error! ${error}`;

      return (
        <img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
      );
    }}
  </Query>
);
```

</div>
</MultiCodeBlock>

By setting the `pollInterval` to 500, you'll fetch the current breed's image from the server every 0.5 seconds. Note that if you set `pollInterval` to `0`, the query will **not** poll.

> You can also start and stop polling dynamically with the `startPolling` and `stopPolling` functions that are returned by the [`useQuery` hook](https://www.apollographql.com/docs/react/api/react/hooks/#usequery).

### Refetching

Refetching enables you to refresh query results in response to a particular user
action, as opposed to using a fixed interval.

Let's add a button to our `DogPhoto` component that calls our query's
`refetch` function whenever it's clicked.

You can optionally provide a new `variables` object to
the `refetch` function. If you don't (as is the case in the following example),
the query uses the same variables that it used in its previous execution.

<MultiCodeBlock>
<div data-language="hooks-js">

```jsx:title=index.js
function DogPhoto({ breed }) {
  const { loading, error, data, refetch } = useQuery(GET_DOG_PHOTO, {
    variables: { breed },
    skip: !breed,
  });

  if (loading) return null;
  if (error) return `Error! ${error}`;

  return (
    <div>
      <img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
      <button onClick={() => refetch()}>Refetch!</button>
    </div>
  );
}
```

</div>
<div data-language="js">

```jsx:title=index.js
const DogPhoto = ({ breed }) => (
  <Query query={GET_DOG_PHOTO} variables={{ breed }} skip={!breed}>
    {({ loading, error, data, refetch }) => {
      if (loading) return null;
      if (error) return `Error! ${error}`;

      return (
        <div>
          <img
            src={data.dog.displayImage}
            style={{ height: 100, width: 100 }}
          />
          <button onClick={() => refetch()}>Refetch!</button>
        </div>
      );
    }}
  </Query>
);
```

</div>
</MultiCodeBlock>

Click the button and notice that the UI updates with a new dog photo. Refetching is an excellent way to guarantee fresh data, but it introduces some complexity with loading state. In the next section, we'll cover strategies for handling complex loading and error state.

## Inspecting loading states

We've already seen that the `useQuery` hook exposes our query's current loading state. This is helpful when a query first loads, but what happens to our loading state when we're refetching or polling?

Let's return to our refetching example from the previous section. If you click the refetch button, you'll see that the component doesn't re-render until the new data arrives. What if we want to indicate to the user that we're refetching the photo?

Luckily, the `useQuery` hook's result object provides fine-grained information about the status of the query via the `networkStatus` property. To take advantage
of this information, we need to set the `notifyOnNetworkStatusChange` option to `true` so our query component re-renders while a refetch is in flight:

<MultiCodeBlock>
<div data-language="hooks-js">

```jsx:title=index.js
function DogPhoto({ breed }) {
  const { loading, error, data, refetch, networkStatus } = useQuery(
    GET_DOG_PHOTO,
    {
      variables: { breed },
      skip: !breed,
      notifyOnNetworkStatusChange: true,
    },
  );

  if (networkStatus === 4) return 'Refetching!';
  if (loading) return null;
  if (error) return `Error! ${error}`;

  return (
    <div>
      <img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
      <button onClick={() => refetch()}>Refetch!</button>
    </div>
  );
}
```

</div>
<div data-language="js">

```jsx:title=index.js
const DogPhoto = ({ breed }) => (
  <Query
    query={GET_DOG_PHOTO}
    variables={{ breed }}
    skip={!breed}
    notifyOnNetworkStatusChange
  >
    {({ loading, error, data, refetch, networkStatus }) => {
      if (networkStatus === 4) return 'Refetching!';
      if (loading) return null;
      if (error) return `Error! ${error}`;

      return (
        <div>
          <img
            src={data.dog.displayImage}
            style={{ height: 100, width: 100 }}
          />
          <button onClick={() => refetch()}>Refetch!</button>
        </div>
      );
    }}
  </Query>
);
```

</div>
</MultiCodeBlock>

The `networkStatus` property is an enum with number values from `1` to `8` that represent different loading states. `4` corresponds to a refetch, but there are also values for polling and pagination. For a full list of all the possible loading states, check out the [source](https://github.com/apollographql/apollo-client/blob/master/src/core/networkStatus.ts).

## Inspecting error states

You can customize your query error handling by providing the `errorPolicy`
configuration option to the `useQuery` hook. The default value is `none`, which tells Apollo Client to treat all GraphQL errors as runtime errors. In this case, Apollo Client discards any query response data returned by the server and sets the `error` property in the `useQuery` result object to `true`.

If you set `errorPolicy` to `all`, `useQuery` does _not_ discard query response data, allowing you to render partial results.

## Executing queries manually

When React mounts and renders a component that calls the `useQuery` hook, Apollo Client automatically executes the specified query. But what if you want to execute a query in response to a different event, such as a user clicking a button?

The `useLazyQuery` hook is perfect for executing queries in response to events
other than component rendering. This hook acts just like `useQuery`, with one key exception: when `useLazyQuery` is called, it does _not_ immediately execute its associated query. Instead, it returns a function in its result tuple that you can call whenever you're ready to execute the query:

```jsx:title=index.js
import React, { useState } from 'react';
import { useLazyQuery } from '@apollo/client';

function DelayedQuery() {
  const [dog, setDog] = useState(null);
  const [getDog, { loading, data }] = useLazyQuery(GET_DOG_PHOTO);

  if (loading) return <p>Loading ...</p>;

  if (data && data.dog) {
    setDog(data.dog);
  }

  return (
    <div>
      {dog && <img src={dog.displayImage} />}
      <button onClick={() => getDog({ variables: { breed: 'bulldog' } })}>
        Click me!
      </button>
    </div>
  );
}
```

> To view a complete version of the app we just built, check out the CodeSandbox [here](https://codesandbox.io/s/n3jykqpxwm).

## useQuery API

Supported options and result fields for the `useQuery` hook are listed below.

Most calls to `useQuery` can omit the majority of these options, but it's useful to know they exist. To learn about the `useQuery` hook API in more detail with usage examples, see the [API reference](../api/react/hooks/#usequery).

### Options

The `useQuery` hook accepts the following options:

<QueryOptions />

### Result

After being called, the `useQuery` hook returns a result object with the following properties. This object contains your query result, plus some helpful functions for refetching, dynamic polling, and pagination.

<QueryResult />

## Next steps

Now that you understand how to fetch data with the `useQuery` hook, [learn how to _update_ your data with the `useMutation` hook!](mutations/)

After that, learn about some other handy Apollo Client features:

- [Local state management](local-state/): Learn how to query local data.
- [Pagination](pagination/): Building lists has never been easier thanks to Apollo Client's `fetchMore` function. Learn more in our pagination tutorial.
