Creating a Reddit Clone Using React and GraphQL — 06
Tags: react, typescript, graphql, redditclone
Published: 2021-02-17 07:17:04

Now we are adding the `GraphQL` request when we are making API calls. To do this we are using `URQL GraphQL Client`. using below command to add the relevant packages to the web app.

```javascript
yarn add urql graphql
```

Then we are adding the provider and client in `_app.tsx` file.

```javascript
// _app.tsx
// add the client
const client = createClient({ url: "http://localhost:4001/graphql" });

<Provider value={client}>// wrap all the components</Provider>;
```

Then we are adding the register mutation on client-side(`urql` hook). Here we are coping the `graphql` query and add the variable to get the username and password from our `graphql` playground.

```javascript
const REGISTER_MUT = `mutation Register($username: String!, $password: String!) {
  register(options:{username:$username,password: $password}){
    user{
      id,
      username
    }
    errors{
      field
      message
    }
  }
}`;
```

Here once we add the mutation as bellow. The first variable in the below array regarding the information on this mutation. At this moment we don’t want it. So we can leave it there as an empty object of leaving a comma as below.

```javascript
const [, register] = useMutation(REGISTER_MUT);
```

The second variable is our function and we call it as `register`. Then we can use it inside the `onSibmit` function as below.

```javascript
onSubmit = {(value) => {register(value)}}
```

Because here value, map with our keys we don’t need to manually assign them. Unless we need to do as below.

```javascript
register({ username: values.username, password: values.password });
```

Now we are adding some options `createClient` method. So we are including the credentials. This will help to get the cookie when you register or login.

```javascript
const client = createClient({
  url: "http://localhost:4001/graphql",
  fetchOptions: {
    credentials: "include",
  },
});
```

Also in `register` method that we used in `onSubmit` function in `register.tsx `file, we are going to return it because it is returning a `Promise` . Unless in the UI, the register button will spin forever.

If we try this now, we will get an `CORS` error. To fix that we are adding our web app origin to Apollo Server.

```javascript
apolloServer.applyMiddleware({
  app,
  cors: {
    origin: "http://localhost:3000",
  },
});
```

But this will only resolve on Apollo server `CORS` . So we can add `cors` to the server project and manage `CORS` globally in the express server. But, this is one way to do it. It depends on how do manage the `CORS` withing your application that only for `GraphQL` or full application.

Add below yarn packages to the server project.

```javascript
yarn add cors
yarn add -D @types/cors
// cors type support
```

Then set `cors` false in the `ApolloServer`. Add `cors` as middleware.

```javascript
app.use(
  cors({
    origin: "http://localhost:3000",
    credentials: true,
  })
);

// change apollo server cors to false
apolloServer.applyMiddleware({ app, cors: false });
```

Also, in your `tsconfig.json` add the below line to bypass the `libCheck`. Because most probably now you will get an error while building the server application codebase.

```javascript
"skipLibCheck": true,
```

Now we fixed the `CORS` error at this moment. After that, we are making some improvement to `register` method as below(make it `async` function) because `register` method returns a Promise.

```javascript
// register.tsx
onSubmit={async (values) => {
  const response = await register(values)
}}

```

Now the issue is the `response` ‘s type is `any` . So let’s change it. We are adding `GraphQL Code Generator` that to the web app project. It looks at our query and generates the `TypeScript` type and generates the `urql` hooks.

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

```

Now we are going to initiate the query generator. For that, execute the below command and set up the config questions.

```javascript
yarn graphql-codegen init
```

After all, questions answered, it will create a `codegen.yml` . In there we change `typescript-react-apollo` that in plugging to `typescript-urql` and add the below package.

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

Also, here is the selection for GraphQL Code Generator.

```javascript

Welcome to GraphQL Code Generator!
Answer few questions and we will setup everything for you.

? What type of application are you building?
Application built with React
? Where is your schema?: (path or url) http:/
/localhost:4001/graphql
? Where are your operations and fragments?: s
rc/graphql/**/*.graphql
? Pick plugins: TypeScript (required by other
 typescript plugins), TypeScript Operations (
operations and fragments), TypeScript React A
pollo (typed components and HOCs)
? Where to write the output: src/generated/gr
aphql.tsx
? Do you want to generate an introspection fi
le? No
? How to name the config file? codegen.yml
? What script in package.json should run the
codegen? gen
Fetching latest versions of selected plugins..

```

Now we add `src/graphql/mutations/register.graphql` file and move our mutation in there. After that run `yarn gen `command. Once you generate the types you can open the `graphql.tsx` file. You will see it created `useRegisterMutation` hook for us.

So, in `register.tsx `file change the `useMutation` method to `useRegisterMutation` method. All others are the same.

```javascript
const [, register] = useRegisterMutation();
```

Now, the `response`’s type will be `RegisterMutation` . Cool, right?

Also, check that in `tsconfig.json strict` property and change it to `true`.

> TypeScript Tips:
>
> `if (response.data)` this will throw an error if data is undefined.
>
> `if (response.data?)` this will return `undefined` if data is undefined.
>
> This is called **Optional Chaining**.

Now we are handling the errors here. Let’s create a utility for it. It will transform `qraphql` error object to `formik` error object.

> Best Practise:
>
> The reason that we use this we have a contract that `graphql` will return the separate error format and `fomik` has a separate error object format. Whenever we use an input field we can reuse this `errorMap`

Here is the `errorMap` utility.

```javascript
export const toErrorMap = (errors: FieldError[]) => {
  const errorMap: Record<string, string> = {};

  // destructed the FieldError { field, message }

  errors.forEach(({ field, message }) => {
    errorMap[field] = message;
  });
  console.log(errorMap);

  return errorMap;
};
```

Then we can use it in the `onSubmit` error handler and pass the `graphql` error object. Let’s try it and see the below result. Cool. It is working.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1wogtwaqc37iauel5h1.png)


Now, let's add a user. Once we register a new user successfully it will set the cookie in the browser.

The codebase for this article that can find in here.

[**rasikag/reddit-clone-webapp**](https://github.com/rasikag/reddit-clone-web/tree/02_urql_support)

[**rasikag/reddit-clone-server**](https://github.com/rasikag/reddit-clone/tree/5_add_sessions)

I will wrap-up this post from here. Soon I will publish the next part of this blog post.

If you have anything to ask regarding this please leave a comment here. Also, I wrote this according to my understanding. So if any point is wrong, don’t hesitate to correct me. I really appreciate you.

That’s for today friends. See you soon. Thank you.

References:

This article series based on the [Ben Award - Fullstack React GraphQL TypeScript Tutorial](https://www.youtube.com/watch?v=I6ypD7qv3Z8). This is amazing tutorial and I highly recommend you to check that out.

Main image [credit](https://www.pexels.com/photo/bird-s-eye-view-of-mountains-during-dawn-2801818/)