Apollo Client to fetch data from GraphQL

Dilip Kumar
4 min readAug 8, 2018

Apollo 2.0 comes with Query as pure react component over graphql Higher Order Component.

Following is sample example.

import { Query } from "react-apollo";
import gql from "graphql-tag";

const ExchangeRates = () => (
<Query
query={gql`
{
rates(currency: "USD") {
currency
rate
}
}
`}
>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return data.rates.map(({ currency, rate }) => (
<div key={currency}>
<p>{`${currency}: ${rate}`}</p>
</div>
));
}}
</Query>
);

Apollo Client takes care of the request cycle from start to finish, including tracking loading and error states for us.

Following happens we fetch data from a Querycomponent.

  1. When the Query component mounts, Apollo Client creates an observable for our query. Our component subscribes to the result of the query via the Apollo Client cache.
  2. First, we try to load the query result from the Apollo cache. If it’s not in there, we send the request to the server.
  3. Once the data comes back, we normalize it and store it in the Apollo cache. Since the Query component subscribes to the result, it updates with the data reactively.

Polling to re-fetch data

Polling can help us achieve near real-time data by causing the query to refetch on a specified interval. To implement polling, simply pass a pollInterval prop to the Query component with the interval in ms. If we pass in 0, the query will not poll.

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

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

Note: It can also implement dynamic polling by using the startPolling and stopPolling functions on the result object passed to the render prop function.

Reload the query in response to a user action

A button can trigger a refetch when clicked to reload data.

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>
);

Manually firing a query

When React mounts a Query component, Apollo Client automatically fires off your query. What if you wanted to delay firing your query until the user performs an action, such as clicking on a button? For this scenario, we want to use an ApolloConsumer component and directly call client.query() instead.

import React, { Component } from 'react';
import { ApolloConsumer } from 'react-apollo';

class DelayedQuery extends Component {
state = { dog: null };

onDogFetched = dog => this.setState(() => ({ dog }));

render() {
return (
<ApolloConsumer>
{client => (
<div>
{this.state.dog && <img src={this.state.dog.displayImage} />}
<button
onClick={async () => {
const { data } = await client.query({
query: GET_DOG_PHOTO,
variables: { breed: "bulldog" }
});
this.onDogFetched(data.dog);
}}
>
Click me!
</button>
</div>
)}
</ApolloConsumer>
);
}
}

Query fetch policy

  • The fetch policy is an option which allows you to specify how you want your component to interact with the Apollo data cache.
  • By default your component will try to read from the cache first, and if the full data for your query is in the cache then Apollo simply returns the data from the cache.
  • If the full data for your query is not in the cache then Apollo will execute your request using your network interface.

Query component provides fetchPolicy option to change default behavior.

Valid fetchPolicy values are:

  • cache-first: This is the default value where it always try reading data from your cache first. If all the data needed to fulfill the query is in the cache then that data will be returned. Apollo will only fetch from the network if a cached result is not available. This fetch policy aims to minimize the number of network requests sent when rendering your component.
  • cache-and-network: This fetch policy will have Apollo first trying to read data from your cache. If all the data needed to fulfill your query is in the cache then that data will be returned. However, regardless of whether or not the full data is in your cache this fetchPolicy will always execute query with the network interface unlike cache-first which will only execute your query if the query data is not in your cache. This fetch policy optimizes for users getting a quick response while also trying to keep cached data consistent with your server data at the cost of extra network requests.
  • network-only: This fetch policy will never return you initial data from the cache. Instead it will always make a request using your network interface to the server. This fetch policy optimizes for data consistency with the server, but at the cost of an instant response to the user when one is available.
  • cache-only: This fetch policy will never execute a query using your network interface. Instead it will always try reading from the cache. If the data for your query does not exist in the cache then an error will be thrown. This fetch policy allows you to only interact with data in your local client cache without making any network requests which keeps your component fast, but means your local data might not be consistent with what is on the server.
  • no-cache: This fetch policy will never return your initial data from the cache. Instead it will always make a request using your network interface to the server. Unlike the network-only policy, it also will not write any data to the cache after the query completes.

--

--