GraphQL is a query language for querying exactly what you want from many resources in a single request. It is intended for clients such as web apps to be more performant and to make it easier to work with backend data.
This guide will demonstrate how to integrate GraphQL into your React app using Apollo Client.
You will use configure Apollo Client and then the useQuery
to retrieve data from graphQL and REST endpoints.
This guide assumes a basic understanding of React Hooks.
Start by creating a new React project by running the following commands:
1npx create-react-app my-graphql-react-project
2cd my-graphql-react-project
3yarn add @apollo/client graphql
These commands set up a new React project and install @apollo/client
, which is a stable and mature graphQL library.
Apollo helps with state management and in-memory caching in your app.
This allows you to achieve more with less code compared to a React Redux project.
To start using ApolloClient
to query a graphQL endpoint in your React app, you must set up a client and make it available to relevant components.
Create the file src/ApolloClient/client.js
and insert the following code.
1import { ApolloClient, ApolloLink, InMemoryCache } from "@apollo/client";
2import { RestLink } from "apollo-link-rest";
3
4const httpLink = new HttpLink({
5 uri: "https://48p1r2roz4.sse.codesandbox.io",
6});
7
8export const client = new ApolloClient({
9 cache: new InMemoryCache(),
10 link: ApolloLink.from([httpLink]),
11});
Two pieces of configuration are required:
link
allows you to customize the flow of data from your graphQL queries and mutations to your backend and in-app state management. This can include: adding custom headers and routing to REST endpoints and graphQL endpoints.cache
allows you to prevent unnecessary networks requests when you already have the data.The code sample above connects to a simple sandbox graphQL endpoint that provides currency exchange rate data.
With the client configuration, you can use React's Context API so that your child components can access your configuration and make queries and mutations.
To do this, update your src/App.js
to the following:
1import React from "react";
2import "./App.css";
3import { client } from "./ApolloClient/client";
4import { ApolloProvider } from '@apollo/client';
5import ExchangeRatesPage from './ExchangeRatesPage';
6
7function App() {
8 return (
9 <ApolloProvider client={client}>
10 <div className="App">
11 <ExchangeRatesPage />
12 </div>
13 </ApolloProvider>
14 );
15}
16
17export default App;
You have imported the client
you created earlier and wrapped everything with the ApolloProvider
component.
These changes are necessary so that the ExchangeRatesPage
component that you will create in the next section knows how to fetch data.
With the ApolloClient
in context, child components of App.js
can use the useQuery
and useLazyQuery
hooks to query data.
This section describes how to use the useQuery
hook.
Create the file src/ExchangeRatePage.js
1import React from "react";
2import { useQuery, gql } from "@apollo/client";
3
4const EXCHANGE_RATES = gql`
5 query GetExchangeRates {
6 rates(currency: "AUD") {
7 currency
8 rate
9 }
10 }
11`;
12
13function ExchangeRatePage() {
14 const { data, loading, error } = useQuery(EXCHANGE_RATES);
15
16 if (loading) {
17 return <div>loading</div>;
18 }
19
20 if (error) {
21 return <div>{error}</div>;
22 }
23
24 return data.rates.map(({ currency, rate }) => (
25 <div key={currency}>
26 <p>
27 {currency}: {rate}
28 </p>
29 </div>
30 ));
31}
32
33export default ExchangeRatePage;
When this component is loaded, it immediately makes the query to the server, and the loading
property is set to true
. Once the data is returned, your component is immediately rerendered and the data
property is populated.
You should notice that there is much less boilerplate to get started querying data. Loading and error states properties are handled for you.
If you would like more control over loading, you can use the useLazyQuery
hook and call the return function when you want to trigger the fetch operation.
If you have a set of REST endpoints, you can still use Apollo and GraphQL to query this data.
To do this, you need to install apollo-rest-link
.
Run the following commands to install the required packages.
1yarn add graphql-anywhere apollo-link-rest
Then update your src/ApolloClient/client.js
file to the following:
1import { ApolloClient, ApolloLink, InMemoryCache } from "@apollo/client";
2import { RestLink } from "apollo-link-rest";
3import { HttpLink } from "apollo-link-http";
4
5const restLink = new RestLink({
6 endpoints: {
7 openExchangeRate: "https://open.exchangerate-api.com/v6/",
8 },
9});
10
11const httpLink = new HttpLink({
12 uri: "https://48p1r2roz4.sse.codesandbox.io",
13});
14
15export const client = new ApolloClient({
16 cache: new InMemoryCache(),
17 link: ApolloLink.from([restLink, httpLink]),
18});
You've now configured two ApolloLinks
:
HttpLink
handles requests to your graphQL endpointRestLink
handles requests to one or more REST endpointsTo activate your RestLink
, you can use the @rest
graphQL directive.
Update your EXCHANAGE_RATES
query to the following:
1onst EXCHANGE_RATES = gql`
2 query GetExchangeRates {
3 rates(currency: "AUD") {
4 currency
5 rate
6 }
7 openExchangeRates @rest(type: "openExchangeRates", path: "/latest", endpoint: "openExchangeRate") {
8 rates
9 }
10 }
11`;
Apollo Client will make a request to your REST endpoint with your graphQL endpoint.
The URI to your rest endpoint will be constructed by combining the path specified in the @rest
directive and endpoint configured in the client.js
.
In this case, the URI would be resolved to https://open.exchangerate-api.com/v6/latest.
The results of your REST request will be appended to the data
property returned from the useQuery
hook.
If your request is successful, the structure of the data property will look like this:
1{
2 "rates": [ { "currency": "AED", "rate": "2.67777" } ],
3 "openExchangeRate": {
4 "rates": { "ARS": 75.17 }
5 }
6}
At the root, the rates
from the graphQL endpoint are unioned with the openExchangeRate
property from the REST endpoint.
From a client perspective, this is convenient since you can benefit from Apollo's caching and state management without completely rewriting your backend to GraphQL.
Interacting with remote data is a large component of modern web apps. Using Apollo and GraphQL, querying data from REST and GraphQL endpoints becomes much easier. As a next step, you may want to explore other Apollo features such as mutations and subscription.