Integrating GraphQL APIs into React app
Tags: nextjs, graphql, urql, typescript
Published: 2021-09-19 10:40:28

In this blog, we'll integrate a GraphQL API into our React app. For testing purposes, I have developed and deployed a public GraphQL API. This API will allow us to perform CRUD operations on **Post**. You can access the playground at [this url] (https://graphql-dummy-api.herokuapp.com/graphql) and refer to the **`DOCS`** and **`SCHEMA`**. You can refer to the code from [this repo](https://github.com/Nazeeh21/integrate-graphql-api-into-react-boilerplate).

We have our GraphQL API, so let us integrate it into our React app.  There is more than one way to integrate GraphQL API to the front end, like using GraphQL clients. But I'll be using a library called [Urql](https://formidable.com/open-source/urql/) instead of any other GraphQL client.

There are mainly 3 reasons for me using it:

- It is lightweight, powerful, and easy to use.
- It is extensible i.e. it allows you to change how you fetch, cache, or subscribe to the data.
- Also, my favorite, it enables us to use GraphQL in our app without much complex configuration.

So, navigate to the **root directory** of our React App and add `urql` to our app by writing the following command.

```shell
yarn add urql graphql
```

As we have added the `urql` package to our web app, we need to configure it. For that create a new file namely `createUrqlClient.ts`. In that create a *urql client* and provide the URL of the API as an argument and export this client as shown below.

```typescript
import { createClient } from "urql";

export const createUrqlClient = createClient({
  url: 'https://graphql-dummy-api.herokuapp.com/graphql'
})
```

Now, to use this client, we need to wrap our `<App />` in `_app.tsx` using the Provider of urql and pass the client as a prop to this provider. You can refer to the `_app.tsx` from [here](https://github.com/Nazeeh21/integrate-graphql-api-into-react-boilerplate/blob/main/pages/_app.tsx).

```javascript
import type { AppProps } from 'next/app';
import { Provider } from 'urql';
import { createUrqlClient } from '../createUrqlClient';

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <Provider value={createUrqlClient}>
        <Component {...pageProps} />
    </Provider>
  );
}
export default MyApp;
```

We are done configuring our Urql client, now let's query our API.

We can query our GraphQL API, as specified in the Urql docs as well. But instead of querying this way, I would prefer using [GraphQL Code Generator](https://www.graphql-code-generator.com/).

*GraphQL Code Generator* is a CLI tool that can generate TypeScript typings out of the GraphQL schema. It analyzes the schema, parses it, and outputs code at a wide variety of formats, based on predefined plugins and user-defined ones. We just need to provide our *GraphQL API URL*, and it will generate all the types.

So, let's add this Code Generator to our app by running the below script.

```shell
yarn add graphql
yarn add -D @graphql-codegen/cli
```

For generating the types, we need to add a typescript plugin by running the below command.

```shell
yarn add -D @graphql-codegen/typescript
```

Now as we have used Urql along with the typescript, we also need to add the TypeScript Urql plugin by running the below code.

```shell
yarn add -D @graphql-codegen/typescript-urql
```

We have added all the necessary plugins of *code generator*, now let's initiate it in our project by running the script below.

```shell
yarn graphql-codegen init
```
After running the above command, it will prompt us with the type of application where we'll select *React tech stack* as shown below.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631112215573/ixr5mR1OR.png)

After that, we need to enter the URL of our GraphQL API.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631112277678/hCIyp_Tas.png)

Select the following settings when prompted.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631112377680/3dPTNknsS.png)

Having `introspection` selected to **no** and naming the script as `gen` continues with the defaults as shown below.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1631112489884/GT64F8YgT.png)

This will create a `codegen.yml`  which will display all the plugins. Also, we can see that a `gen` script has been added to our `package.json`.

Now, before generating the types, we need to write the graphql queries and mutations. So let's write a simple query to fetch all the posts in our `src/graphql/query/getPosts.graphql` file.

```graphql
query Posts($limit: Int!, $cursor: String) {
  posts(cursor: $cursor, limit: $limit) {
    hasMore
    posts {
      id
      title
      text
    }
  }
}
```

Similarly, let's write mutations to perform create, update and delete to Posts. In `/graphql/mutations/createPost.graphql`, lets write mutation to create Post.

```graphql
mutation CreatePost($input: PostInput!) {
  createPost(input: $input) {
    id
    createdAt
    updatedAt
    title
    text
  }
}
```

Similarly, for updating Post in `/graphql/mutations/updatePost.graphql` file.

```graphql
mutation UpdatePost($id: Int!, $title: String!, $text: String!) {
  updatePost(id: $id, title: $title, text: $text) {
    id
    text
    title
    textSnippet
  }
}
```

For deleting Post in `/graphql/mutations/deletePost.graphql` file.

```graphql
mutation DeletePost($id: Int!) {
  deletePost(id: $id)
}
```

Navigate to the `codegem.yml` file in your root and update its content as below.

```yml
overwrite: true
schema: "https://graphql-dummy-api.herokuapp.com/graphql"
documents: "graphql/**/*.graphql"
generates:
  generated/graphql.tsx:
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-urql"
```

We have all the queries and mutations ready, lets generate the typescript types for our Graphql schema by running the command `yarn gen` in our root directory. This will generate a new file `generated/graphql.tsx` containing all the types of our Graphql schema.

As we have generated the types of our query using codegen, let us fetch all posts. In `index.tsx`, copy the below code. You can refer `index.tsx` from [here](https://github.com/Nazeeh21/integrate-graphql-api-into-react-boilerplate/blob/main/pages/index.tsx)

```javascript
const [{ data, error }] = usePostsQuery({
    variables: {
      limit: 10,
    },
  });
```

Make sure that `usePostsQuery` is imported from the `generated/graphql.tsx` file. In this, we need to pass arguments as an object in variables.

We got all the Posts in this data variable. So let's render it in our frontend. You can find the `Post` component [here](https://github.com/Nazeeh21/integrate-graphql-api-into-react-boilerplate/blob/main/components/Post.tsx).

Let's mutate our post's data. In the provided [Post component](https://github.com/Nazeeh21/integrate-graphql-api-into-react-boilerplate/blob/main/components/Post.tsx), I have added the **Update-post** and **Delete-post** buttons, so let's add the `onClick` handler to both the buttons and the logic to it.

For the **Delete Post**, copy the below code.

```javascript
const [, deletePost] = useDeletePostMutation();

  const onDeletePost = async () => {
    setLoading(true);
    await deletePost({ id });
    router.reload()
    setLoading(false);
  };
```

Similarly, let's add *click handler* to **Update Post**. You can refer to the `UpdatePost` Component [here](https://github.com/Nazeeh21/integrate-graphql-api-into-react-boilerplate/blob/main/components/updatePost.tsx). In the onClick handler add the *update-post* logic from below.

```javascript
 const [, updatePost] = useUpdatePostMutation()

  const updatePostClicked = async () => {
    setLoading(true);
    await updatePost({
      id: +postId!,
      text,
      title
    })
    setLoading(false);
    router.push('/');
  };

```
Make sure `useUpdatePostMutation()` and `useDeletePostMutation()` are imported from `/src/generated/graphql.tsx`.

All these CRUD operations can be done using other libraries too but using the correct combination of packages makes our task a lot easier and as we can notice using codegen has made our task quite easy.