GraphQL API Requests with Typescript, React Query & GraphQL Code Generator
Tags: typescript, react, graphql, javascript
Published: 2022-01-02 12:01:51

In this article, we'll learn how to make GraphQL requests in the client-side of our React application with React Query, Typescript(TS) and also automatically generate TS types for our queries with GraphQL Code Generator. The following paragraphs will be explaining the essence of these technologies.

The first is Typescript(TS) which is gaining huge popularity these days and lots of developers are migrating their projects from plain Javascript to TS. Typescript being a superset of Javascript provides optional static typing making it easy to detect errors during development.

Next is GraphQL, a query language for APIs. With GraphQL, developers can get all the data needed in their application in a single request without having to under-fetch or over-fetch, unlike in REST APIs. One cool feature about GraphQL is the fact that it uses a type system(schema) to describe data queries and mutations.

Now leveraging on this feature of GraphQL schema being typed, we can turn it into Typescript types in our application frontend offering you a better developer experience since they are both typed. But, to ensure type-safety we'll be using a tool called **GraphQL Codegen** to help us auto-generate correct types based on our schema and also get fully typed custom React hooks for  React Query.

Moving on, as developers, there are scenarios where we might not want to use a heavyweight library to fetch GraphQL API for example Apollo in our projects but would prefer a lightweight library to perform the operation. This is where React Query(a library that interacts with our API) comes into play coupled with a library called graphql-request which is pretty much like Axios or fetch but tailored to make just graphql requests.

Let's go ahead to setup the project!

### Prerequisites
This article will assume you have some familiarity with using React Query and Typescript. Also, basic knowledge of GraphQL will come in handy.

### Create React App
To create a new React app with the `--typescript` template flag,
 run;
```
yarn create react-app client --template typescript
```
> If you're having issues creating a new react app due to the recent version upgrade, check out this [article](https://annysah.hashnode.dev/fix-the-error-you-are-running-create-react-app-403-which-is-behind-the-latest-release-500-we-no-longer-support-global-installation-ckxrocpkn0147u5s1ete59bsb) on how to fix it.

Then, start the development server by running
```
yarn start
```

### Setup React Query
Let's install React Query library by executing the following command;
```
yarn add react-query
```
Then, open up the `index.tsx` file in the project folder and set up React Query client;
```
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

import { QueryClient, QueryClientProvider } from "react-query";

const queryClient = new QueryClient();

ReactDOM.render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>,
  document.getElementById('root')
);

```
Here we instantiated the React query client and then wrapped our top-level component within the React query client provider.


### Scaffolding out the App
In the src folder of the project, create a folder called components. Right in this `components` folder, create a `Countries.tsx` file. The `Countries` component will display lists of countries from the free public GraphQL [Countries](https://countries.trevorblades.com/graphql) API we'll be using in this tutorial.

For the purpose of styling the component interface, Tailwind CSS will be used. Now, add the CDN link written below to the head tag of the public/index.html file.

```
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
```

In the `Countries` component, add the following code;

```
import React from "react";

const Countries: React.FunctionComponent = () => {
 
  return (
          <div className="bg-white rounded-lg shadow-md w-80 text-center">
            <div className="mt-4 p-10 text-bold">
              <p>Country</p>
              <p>Capital</p>
              <p>Continent</p>
            </div>
          </div>
  );
};

export default Countries;

``` 
Next, open the `App.tsx` file in the project folder and update like so

```
import React from "react";

import Countries from "./components/Countries";

const App = () => {
  return (
    <>
      <div className="bg-blue-100">
        <header className="text-3xl text-center font-bold pt-6">Countries</header>
        <div className="flex justify-center pb-2">
          <div className="flex flex-col">
            <div className="flex-grow">
              <div className="m-4 grid grid-cols-2 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 gap-8 mt-8">
                <Countries />
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  );
};

export default App;

``` 

### Install GraphQL-Request Library
This library will basically provide a function that accepts an endpoint. Type the following command in your terminal, so we can install `graphlql-request` into our project

```
yarn add graphql graphql-request
```
The `graphql` added above is a dependency for `graphql-request`.

Now update the `Countries` component like so

```
import React from "react";

import { GraphQLClient } from "graphql-request";

const graphqlClient = new GraphQLClient(
  "https://countries.trevorblades.com/graphql"
);

const Countries: React.FunctionComponent = () => {
 
  return (
          <div className="bg-white rounded-lg shadow-md w-80 text-center">
            <div className="mt-4 p-10 text-bold">
              <p>Country</p>
              <p>Capital</p>
              <p>Continent</p>
            </div>
          </div>
  );
};

export default Countries;

```
Here, we basically imported `GraphQLClient` from `graphql-request` and instantiated it. 
### Write Queries
Next, we need to create a `countries.graphql` file in the src folder. In this file, we'll define a query to get the list of countries data we need; the country names, capital and continents.

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

### Setup GraphQL Codegen
Now, let's install `graphql-code-generator` so we can have it up and running in our application. Execute the following command;
 
```
yarn add -D  @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-react-query  @graphql-codegen/typescript-operations
``` 
From the above, we installed 
- `graphql-codegen` CLI so we can run our `codegen` script.
- `graphql-codegen/typescript` and `graphql-codegen/typescript-operations` plugins so we can get our generated types.
- `graphql-codegen/typescript-react-query` plugin in order to generate custom React Query hooks.

Let's also create a `codegen.yml` file where we'll configure how we want our code to be generated.

```
overwrite: true
schema: "https://countries.trevorblades.com/graphql"
documents: "src/**/*.graphql"
generates:
  src/generated/index.ts:
    plugins:
      - "typescript"
      - "typescript-operations"
      - typescript-react-query
    config:
        fetcher: graphql-request
``` 
- `schema` is the URL for the free public GraphQL API we are using in this tutorial.
- `documents` tells `graphql-codegen` to locate `graphql` files, in this case the `countries.graphql` file.
- `generates` defines the file path where the types will be generated once we run a defined `graphql-codegen` script.
- `plugins` represents the plugins we installed earlier.
- `fetcher` configuration lets `graphql-codegen` know we are using `graphql-request` to fetch our data.

Then, let's add our `graphql-codegen` script into our package.json file like so;

![codegen.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1641067875574/wNQ_Ay1XC.png)

Next, let's run our script so we can have generated custom types added automatically to our project `src` as a folder titled `generated`;
 
```
yarn generate

```
### Display the Data
In the `Countries` componet, let's update our code as shown below;
```
import React from "react";

import { GraphQLClient } from "graphql-request";

import { CountriesQuery, useCountriesQuery } from "../generated";

const graphqlClient = new GraphQLClient(
  "https://countries.trevorblades.com/graphql"
);

const Countries: React.FunctionComponent = () => {
  const { data, isLoading, error } = useCountriesQuery<CountriesQuery, Error>(
    graphqlClient,
    {}
  );

  if (isLoading) {
    return <div className="box">Loading...</div>;
  }

  if (error) {
    return <div>Error!</div>;
  }

  return (
    <>
      {data?.countries?.map((country) => {
        return (
          <div className="bg-white rounded-lg shadow-md w-80 text-center">
            <div className="mt-4 p-10 text-bold">
              <p>Country: {country.name}</p>
              <p>Capital: {country.capital}</p>
              <p>Continent: {country.continent.name}</p>
            </div>
          </div>
        );
      })}
    </>
  );
};

export default Countries;

```
From the code above, to interact with the Countries API we are importing the fully typed custom hooks generated by `graphql-codegen` in place of the usual `useQuery` hook from React Query library. Then, we looped through the response data to display the lists of countries, capital and continents.

Now you have it!. The final application should look like this;

![display.PNG](https://cdn.hashnode.com/res/hashnode/image/upload/v1641070831898/L_KqLGwP7.png)

You can access the project source code in this [Github repo](https://github.com/Annysah/react-ts-graphql). Thanks for reading!

### Conclusion
In this article, we were able to make GraphQL API request successfully in our client-side application. By also incorporating the power of the GraphQL codegen library, we were able to generate fully typed custom React Query hooks for our application from the GraphQL schema.