Lewislbr

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.



If you're using dark mode, do you like the code blocks's theme? I have it available for VS Code, feel free to check it.