Apollo Client
Apollo Client is the client-side counterpart to Apollo Server. We use it for managing queries and mutations from the frontend to our Apollo GraphQL server. It is specifically designed to work with React.
We will be working with the schema we defined when working on the server
Initializing the client
We initialise the client and set-up in memory caching to reduce network requests:
const client = new ApolloClient({
uri: "http://localhost:4000",
cache: new InMemoryCache(),
});
The
uri
property must match the location of our Apollo server.
Utilising the provider
Apollo provides a top level application context that we can wrap our React app in. This will provide access to the client object from anywhere within the app, eg:
ReactDOM.render(
<ApolloProvider client={client}>
<GlobalStyles />
<Pages />
</ApolloProvider>,
document.getElementById("root")
);
Running a query
Queries as entry points
From the client point of view, the queries in the schema are entry points. Although the queries exist in the schema, this alone is not sufficient for them to be entry points. Remember a schema is just a specification or contract between the frontend and the backend, it is not itself executable code.
Therefore, for each query in the schema we must write a frontend implementation. We do this with query constants. The frontend implementation has a backend analogue: the resolver that is invoked when the frontend issues a query. The schema standardises this relationship so that every query on the client must have a corresponding resolver on the backend.
Query constants
To run a query against our server we must define a query contant first. We use a gql
literal again:
import { gql } from "@apollo/client";
const TRACKS = gql`
query GetTracks {
tracksForHome {
id
title
thumbnail
length
modulesCount
author {
name
photo
}
}
}
`;
The convention is to name the query constant in ALL_CAPS
.
Note that the name of the query on the client doesn’t have to match the query type defined in the schema (there is no
GetTracks
in the schema), this is just a client-side designator. However it should reference the schema on the second line (tracksForHome
).
useQuery
hook
The useQuery
hook provides a straightforward wrapper for sending queries and receiving data back from the server.
When a component renders, useQuery
returns an object from the Apollo Client that contains loading, error, and data properties.
const { loading, error, data } = useQuery(TRACKS);
const Tracks = () => {
const { loading, error, data } = useQuery(TRACKS);
if (loading) return "Loading...";
if (error) return `Error! ${error.message}`;
return <Layout grid>{JSON.stringify(data)}</Layout>;
};
- We destructure the
loading, error, data
variables that are returned from the hook - We pass in our query constant as an argument.
- In the example we just render the serialized data but we could of course pass the data as a prop and map through it in an embedded child component.