Intro to GraphQL and React using TypeScript
Tags: typescript, react, graphql
Published: 2020-09-01 14:26:39

---
title: Intro to GraphQL and React using TypeScript
published: true
date: 2020-08-26 00:00:00 UTC
tags: typescript,react,graphql
canonical_url: https://nainacodes.com/blog/intro-to-graphql-and-react-with-typescript
---

GraphQL is a modern way of requesting data from the server to the client. It is a query language that allows the client to describe the data it needs.

There are three characteristics of GraphQL that differentiates it from REST APIs. **First** , with GraphQL, you can get exactly what you need, nothing more or nothing less (under fetching or over fetching). You can request the exact piece data you need.

**Second** , you can get multiple data from different sources in just one single query. With REST API, you may need to make multiple request to get all the data.

**Third** , it uses a type system to describe what data can clients request.

In this tutorial, I will show you the basics of how to use GraphQL with React and TypeScript. We are going to use Apollo Client to consume GraphQL API. Apollo is a set of tools we can use to query and also set up a GraphQL server.

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#query-structure)Query structure

The structure of a GraphQL query looks something like this.

```
query Countries {
  countries {
    name
    code
    capital
  }
}
```

The _query_ keyword indicates the operation type. This means that the operation type is a query, which is equivalent to a GET request in REST. We can also have a _mutation_, which is for POST, PUT, PATCH, and DELETE in REST.

_Countries_ is the name of the query, but we can also have an anonymous one (without a name).

```
query {
    countries {
        name
        code
        capital
    }
}
```

After the query, we now specify the fields that we want to get. Here, we are getting the list of countries, and for each country, we are getting its name, code, and capital.

There are many other things you can specify in a query, such as variables, fragments, and directives. If you want to dive dive deeper into the anatomy of a GraphQL query, check out this post. [Anatomy of a graphql query](https://www.apollographql.com/blog/the-anatomy-of-a-graphql-query-6dffa9e9e747/)

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#setting-up-apollo)Setting up Apollo

As mentioned earlier, Apollo is a set of tools that makes is it easier for developers to work with GraphQL. We have the Apollo Client and the Apollo Server.

Apollo Client is what you use to consume GraphQL API, and it supports popular frontend frameworks such as React, Angular, Vue, and more. This is what we're gonna use in this tutorial together with React.

Apollo Server is what you use to set up a GraphQL server and send responses back to the client. In this post, we are not going to create our own server, but instead we are going to use a public GraphQL API for information about countries to demonstrate how to use GraphQL queries.

([https://github.com/trevorblades/countries](https://github.com/trevorblades/countries))

So, to use Apollo Client with React, we first need to install all the necessary packages. I assume that you already have a TypeScript React project set up at this point 🙂

```
npm install @apollo/client graphql
```

After installation, we need to create a client. In the _index.tsx_ file, copy the following piece of code.

```typescript
import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://countries.trevorblades.com/',
  cache: new InMemoryCache(),
});
```

We are instantiating a new object from the ApolloClient class, and we are passing the options for our client in the constructor. The _uri_ points to the url of the GraphQL server, and the cache is the [caching strategy](https://www.apollographql.com/docs/react/caching/cache-configuration/) we're going to use with the client. _InMemoryCache_ is the default mechanism provided by Apollo, and it's a good one to start with.

After creating a client, we now need to connect our React app to the client. We can do this by wrapping the `<App />` component with the ApolloProvider.

```typescript
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://countries.trevorblades.com/',
  cache: new InMemoryCache(),
});

const App: FunctionComponent = () => <CountryList />;

render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);
```

We pass the an ApolloClient to the ApolloProvider as a prop. Any component nested in between the ApolloProvider can now perform GraphQL operations.

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#making-your-first-query)Making your first query

We are ready to do our first GraphQL query. The uri of the GraphQL server that our app is pointing to provides information about countries, capital, continent, and other information. So for our first query, we are going to create a `<CountryList/>` component that will list of all the countries around the world together with their capital city and continent.

We are going to create a new file called `CountryList.tsx`. The content of this file will be like this:

```typescript
import React, { Fragment } from 'react';
import { useQuery, gql } from '@apollo/client';

interface Country {
  name: string;
  code: string;
  capital: string;
  continent: {
    name: string;
  };
}

interface CountryData {
  countries: Country[];
}

const COUNTRIES_QUERY = gql`
  query Countries {
    countries {
      name
      code
      capital
      continent {
        name
        code
      }
    }
  }
`;

const CountryList: FunctionComponent = () => {
  const { data, loading, error } = useQuery<CountryData>(COUNTRIES_QUERY);
  if (loading) {
    return <p>Loading...</p>;
  }
  const { countries } = data;

  return (
    <>
      {countries.map((c, i) => (
        <div key={i}>
          {c.name} - {c.capital} - {c.continent.name}
        </div>
      ))}
    </>
  );
};

export default CountryList;
```

We defined our GraphQL query in a constant called COUNTRIES\_QUERY. It uses `gql`, a parser function that parses our plain string containing GraphQL code. In this query, we are requesting a list of countries, with their name, code, capital and continent. This is the nice thing about GraphQL because we can specify exactly what fields we need.

Then, inside the CountryList component, we use a custom React hook provided by Apollo to execute our query. The `useQuery` hook fetches the GraphQL query and returns a result that we can use in our UI.

The `useQuery` hook returns a data property (we destructured it) that basically contains the information we requested for. But it also returns a loading property, and an error property. Here, we are using the loading property to show a loading message while data is being fetched. You can console log the result of `useQuery` to see all the available properties returned.

The data property contains the list of countries, so we just map through the list and return the jsx containing the name, capital and continent of the country. Notice how we also typed the data returned by `useQuery` hook to be of type CountryData.

So yea, making a query is as simple as that 😉

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#query-with-parameters)Query with parameters

Let us say we only want to get European countries. How do we do that? GraphQL allows us pass variables in the query. It is like the query params in REST, but more powerful.

We can modify our query constant above to something like this.

```typescript
const COUNTRIES_QUERY = gql`
  query Countries {
    countries(filter: { continent: { eq: "EU" } }) {
      name
      code
      capital
      continent {
        name
        code
      }
    }
  }
`;
```

Our GraphQL endpoint allows us to pass a filter object to filter the results. This is how the server was set up. What we pass here depends on your GraphQL endpoint. So here we are simply getting countries that have continent code equal to "EU". If you replace the constant above with this one, you will only get European countries in your list.

That is pretty static, because we hard-coded the filter, but we can also make it dynamic.

```
const COUNTRIES_QUERY = gql`
  query Counties($code: String) {
    countries(filter: { continent: { eq: $code } }) {
      name
      code
      capital
      continent {
        name
        code
      }
    }
  }
`;
```

The code we pass in the filter is now dynamic. The `$code` is of type string, and we use that value in the filter for countries.

To pass the actual value, we can change our `useQuery` hook to this.

```
const continentCode = 'EU';
const { data, loading } = useQuery<CountryData>(COUNTRIES_QUERY, {
  variables: {
    code: continentCode,
  },
});
```

The `useQuery` hook accepts a second argument as object, and that is where we pass our argument for the parameter in our query.

Here is the final code. Notice that we have also typed our query variables with CountryVariable interface.

```typescript
import React, { Fragment } from 'react';
import { useQuery, gql } from '@apollo/client';

interface Country {
  name: string;
  code: string;
  capital: string;
  continent: {
    name: string;
  };
}

interface CountryData {
  countries: Country[];
}

interface CountryVariable {
  code: string;
}

const COUNTRIES_QUERY = gql`
  query Counties($code: String) {
    countries(filter: { continent: { eq: $code } }) {
      name
      code
      capital
      continent {
        name
      }
    }
  }
`;

const CountryList = () => {
  const continentCode = 'EU';
  const { data, loading } = useQuery<CountryData, CountryVariable>(COUNTRIES_QUERY, {
    variables: {
      code: continentCode,
    },
  });

  if (loading) return <p>Loading...</p>;
  const { countries } = data;

  return (
    <>
      {countries.map((c, i) => (
        <div key={i}>
          {c.name} - {c.capital} - {c.continent.name}
        </div>
      ))}
    </>
  );
};

export default CountryList;
```

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#mutation)Mutation

If you want to make a POST, PUT, PATCH, or DELETE http request, then you have to use GraphQL mutations. Since the GraphQL endpoint we are using doesn't have mutations, I'm just going to show you how it is done, but we won't be able to test it.

First, you have to create a mutation operation.

```
const ADD_COUNTRY_MUTATION = gql`
  mutation AddCountry($country: Country) {
    addCountry(country: $country) {
      name
      code
      capital
    }
  }
`;
```

We use the mutation keyword, and we pass the data (country) that we want to insert as an argument to the GraphQL operation. `$country` is of type Country (which is defined in your GraphQL schema in the server). After the operation is successful, we will return the name, code, and capital of the country.

Next, to actually execute the operation, we need to use the `useMutation` hook provided by Apollo client.

```typescript
import { useMutation } from '@apollo/client';

interface Country {
  id: string;
  name: string;
  code: string;
  capital: string;
  continent: string;
}

interface FormData {
  country: Country;
}

const ADD_COUNTRY_MUTATION = gql`
  mutation AddCountry($country: Country) {
    addCountry(country: $country) {
      name
      code
      capital
    }
  }
`;

const CountryForm = () => {
  const dummyFormData: FormData = {
    id: 'FXJ32JD',
    code: 'FR',
    name: 'France',
    capital: 'Paris',
    continent: 'Europe',
  };

  const [addCountry, { data }] = useMutation<Country, FormData>(ADD_COUNTRY_MUTATION, {
    variables: {
      country: dummyFormData,
    },
  });

  return (
    <>
      <button onClick={addCountry}>Add new country</button>
    </>
  );
};

export default CountryForm;
```

Like the `useQuery` hook, `useMutation` accepts 2 arguments, the first one is the mutation operation, and the second one is an object that contains the variables to pass to the mutation. Our POST data is going to be passed as a variable in the second argument.

The `useMutation` hook doesn't immediately execute the query, but instead it returns to us an array that contains the mutation function. The first item in the array is the mutate function (as which we assign to `addCountry`), and the second item is the data that is returned. In the example, we are both destructuring the values ([array destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)). You can call the `addCountry` mutation function anytime to execute the query.

And that's it. Whether you want to perform a POST, PUT, or a DELETE, you basically follow the same thing.

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#conclusion)Conclusion

This is a simple introduction to using queries and mutations with React and TypeScript. There's still a lot that you can learn, but knowing the basics will definitely help you continue with your learning. Maybe in a future post, I will also show how to setup a GraphQL server.

Feel free to play around with the code in this [Stackblitz project](https://stackblitz.com/edit/getting-started-with-graphql-react?file=CountryList.tsx).

Thanks for reading! If this has helped you, kindly please share 😎