Short intro to Apollo Client with TypeScript

15.01.20184 Min Read — In Coding

What the hell is GraphQL?

You have probably been hearing of GraphQL - the new hype technology in the field of API technologies. In short, GraphQL is a syntax that describes how to ask for data. While most developers have been using REST API’s for quite a while now, GraphQL brings several advantages advantages over REST:

  1. It’s enables the client to specify exactly which data (and respective fields) it wants. REST endpoints usally return the whole requested entity.
  2. Enables an easier aggregation of multiple data sources preventing mutiple requests
  3. Finally, it uses a type system to ensure type-safety on the receiving data. That's really nice.

Why should I use a GraphQL Client?

If you want your frontend application to be able to consume and produce data via GraphQL, you should use one of the many GraphQL clients out there. By doing so, you avoid repetitive and agnostic work, for example, when creating query and mutation payloads and prevent headaches when having to deal with low level networking and caching funtionalities. Short hint, in the following example we will be using the popular Apollo Client.

This article

In the following example, I will show you how to setup a GraphQL Apollo Client with a basic React application. Then, we will fires a GraphQL Query and render the received data. In this example we will be contacting the publicly available GraphLoc GraphQL API which will give us location data in exchange for an IP 🖲.

So let's check the IP of my blog:

Alt Text

Initialising the Client

In order to even start using Apollo Client, we will have to install following packages: npm install apollo-boost graphql graphql-tag react-apollo. Once all these dependencies are installed we can initalize the Apollo Client.

import * as React from "react";
import { render } from "react-dom";
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";

const IP = "104.198.14.52";
const client = new ApolloClient({ uri: "https://api.graphloc.com/graphql" });

const App: React.FunctionComponent = () => (
  <ApolloProvider client={client}>...</ApolloProvider>
);

export default App;

Simply initalise the client and Wrap the whole application in the ApolloProvider component.

Writing the Query & Component

Before we write the GraphQL query it is important to know which shape our data has. Thanks to the typing of GraphQL, tools like GraphiQL or GraphQL playground can help inspect the available schema and make our lives much easier when writing queries and mutations.

Alt Text

The above exmaple shows GraphiQL schema with the getLocation query on the left side and the response coming back from the /graphql endpoint on the right.

const QUERY = gql`
  query getLocation($ip: String!) {
    getLocation(ip: $ip) {
      country {
        names {
          en
        }
        geoname_id
        iso_code
      }
      location {
        latitude
        longitude
      }
    }
  }
`;

Based on the query we can define the respective typings for the payload we receive from the server as response:

type GetLocationResponse = {
  getLocation: {
    country: {
      names: {
        en: string
      }
    },
    location: {
      latitude: string,
      longitude: string
    }
  }
};

We also need to include typing for the variables input (in this case the ip) which is passed to the GraphQL query.

type GetLocationVaribales = {
  ip: string
};

Once we have the typings for the repsonse and the varibles and the query written down, we can combine them altogether in the LocationQuery component.

const LocationQuery: React.FC<Props> = ({ children, variables }) => (
  <Query<GetLocationResponse, GetLocationVaribales>
    query={QUERY}
    variables={variables}
  >
    {({ error, loading, data }) => {
      const { getLocation = null } = data || {};
      return children({ error, loading, data: getLocation });
    }}
  </Query>
);

The reponse of the query is passed to the render props of the query component. From there we will pass the Query's loading, error and data into the children property of the LocationQuery component for the children component to handle the incoming data.

Recieving and rendering the Data

<LocationQuery variables={{ ip: IP }}>
  {({ error, loading, data }) => {
    if (error) {
      return <p> 💩 Something is wrong... </p>;
    }
    if (loading) {
      return <p>loading...</p>;
    }
    if (data) {
      return (
        <>
          <h1>{`The IP ${IP} is coming from...🥁`}</h1>
          <p>Country: {data.country.names.en}</p>
          <p>Latitude: {data.location.latitude}</p>
          <p>Longitude: {data.location.longitude}</p>
        </>
      );
    }
    return <h1>No data.</h1>;
  }}
</LocationQuery>

Now we can use the LocationQuery component use it's children component to handle the received location information. Below you will find a CodeSandbox with all the code from this tutorial.

Wrapping things up

In this article you have seen how to initialise Apollo Client and how to fire a Query to a remote GraphQL server. By using the render prop pattern, we ticked all the request logic and typings in a single Query component. Thanks for reading 🤩.