Implement Apollo Client with React and TypeScript
I love Apollo Client. It allows us to handle GraphQL data in the frontend flawlessly. In this post we’ll see how to implement Apollo Client in a React with TypeScript application, and how to make type-safe queries and mutations.
Set Up
Let’s imagine we have a backend with a GraphQL endpoint at http://localhost:4040/animals
that serves us data about animals.
To get that data in the frontend, we need to install some packages:
npm i @apollo/client graphql
Now we can configure Apollo Client in our root index.tsx
file:
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
ApolloClient,
ApolloProvider,
HttpLink,
InMemoryCache,
} from "@apollo/client";
import { App } from "./App";
const client = new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: "http://localhost:4040/animals",
}),
});
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
document.getElementById("root")
);
This will allow us to acces the data from any part of the application.
Type Generation
From here we could already use what we have to get data correctly, but without any type safety. To fix that, we will use the Apollo CLI, an awesome tool that will create TypeScript types from the backend schema.
We can use it by just running one command:
npx apollo client:codegen --target=typescript --addTypename --endpoint=http://localhost:4040/animals --outputFlat=src/graphql
In this command we basically define where the GraphQL endpoint is, where to generate the files with the types, and some configuration options.
Usage
Now we can go to a component that will get the data and display a list of animals, like Animals.tsx
, import the query hook, build the query we need, and access fully-typed data
, loading
and error
properties from Apollo Client:
import React from "react";
import { gql, useQuery } from "@apollo/client";
import { Animals } from "../graphql/Animals";
const ANIMALS = gql`
query GetAnimals {
getAnimals {
_id
name
}
}
`;
export function Animals(): JSX.Element {
const { data, loading, error } = useQuery<Animals>(ANIMALS);
return (
<>
<section>
<h1>{"Animals"}</h1>
</section>
<section>
{loading ? (
<p>{"Loading..."}</p>
) : error ? (
<p>{"ERROR"}</p>
) : (
<div>
{data?.getAnimals?.map((animal) => (
<div key={animal.id}>
<h2>{animal.name}</h2>
</div>
))}
</div>
)}
</section>
</>
);
}
Done!
I find this combination of React, TypeScript, Apollo Client and Apollo CLI to be super powerful, and provides us a great abstraction without hiding the implementation of it.