GraphQL Data Fetching with SWR React Hooks and Hasura
Tags: swr, frontend
Published: 2020-12-15 10:30:39

---
title: GraphQL Data Fetching with SWR React Hooks and Hasura
published: true
date: 2020-12-14 11:48:11 UTC
tags: SWR,Frontend
canonical_url: https://hasura.io/blog/graphql-data-fetching-swr-react-hooks-hasura/
---

 ![GraphQL Data Fetching with SWR React Hooks and Hasura](https://hasura.io/blog/content/images/2020/12/swr_hasura_graphql_data_fetching.png)

From [SWR's github repo](https://github.com/vercel/swr):

_The name “ **SWR** ” is derived from `stale-while-revalidate`, a cache invalidation strategy popularized by [HTTP RFC 5861](https://tools.ietf.org/html/rfc5861). **SWR** first returns the data from cache (stale), then sends the fetch request (revalidate), and finally comes with the up-to-date data again._

GraphQL requests are just HTTP POST requests with a JSON payload at the end of the day. It doesn't need the typical setup overhead for data fetching. Popular GraphQL clients have made it look slightly complicated than a normal fetch request counterpart, but for added benefits like caching.

The SWR API is simple and looks like the one below:

```
const { data, error, isValidating, mutate } = useSWR(key, fetcher, options)
```

We will focus on the arguments `key` and `fetcher`. In a GraphQL API implementation with SWR, the GraphQL document will be the key that will be used. In REST APIs, the URL endpoint will usually be the key (something like `/api/users`. The `fetcher` function is an async function that returns the data. It gets the key and the logic of data fetching is written inside this. We will split our logic between HTTP POST requests and native websocket connections here.

The unique key ensures that requests are not sent multiple times if used in different components in the same page.

We can use simple data fetching libraries like `graphqurl` or `graphql-request` to send a GraphQL query. In the example below, I'm sticking to native `fetch` library for making the HTTP POST API calls and native `WebSocket` client.

The idea behind this example is to demonstrate usage of `useSWR`, `mutate` and `trigger` hooks of `SWR` in combination with GraphQL. We need a GraphQL API and we are going to make use of Hasura Cloud to get it instantly.

<!--kg-card-begin: markdown-->
## Deploy Hasura to get a GraphQL API

1. 

Click on the following button to deploy GraphQL engine on Hasura Cloud including Postgres add-on or using an existing Postgres database:

[![GraphQL Data Fetching with SWR React Hooks and Hasura](https://graphql-engine-cdn.hasura.io/img/deploy_to_hasura.png)](https://cloud.hasura.io/)

2. 

Open the Hasura console

Click on the button "Launch console" to open the Hasura console.

3. 

Create table users

Head to the `Data` tab and create a new table called `users` with columns:

  - id (text)
  - name (text)
  - created\_at (timestamp now()).
4. 

Try out a GraphQL Query

```
query {
    users {
        id
        name
        created_at
    }
}

```
<!--kg-card-end: markdown-->

We are going to make use of the above `users` query inside our react frontend.

Clone the `swr-graphql` repo and head to the `libs` directory that contains the wrapper for both fetch and websockets. Change the GraphQL endpoint to point to the Hasura Cloud project URL.

### GraphQL Query

The `useSWR` hook gets a graphql query as the key and the fetcher function is defined in `getData`. We have written a custom `fetch` method in the libs directory.

```
import useSWR from 'swr'

const query = {
  'query': 'query { users(limit:10, order_by:{created_at: desc}) { id name } }'
};

const getData = async(...args) => {
  return await fetch(query);
};

export default () => {
  const { data, error } = useSWR(query, getData);
  if(error) {
    return <div>Error...</div>
  }
  if(!data) {
    return <div>Loading...</div>
  }
}
```

The hook returns the data / error and the respective states can be handled on the rendering logic.

### GraphQL Mutation

Once a mutation is done, you would want to update existing state by modifying data (addition / removals / updates). This is possible via the `mutate` method, where a `key` can be passed (GraphQL query will be the key for us) and the new data to be used along with a boolean to specify whether you want to revalidate or not.

```
export default () => {
  const [text, setText] = React.useState('');
  const { data } = useSWR(query, getData)

  async function handleSubmit(event) {
    event.preventDefault()
    // mutate current data to optimistically update the UI
    mutate(query, {users: [...data.users, {id: uuidv4(), name: text}]}, false)
    // send text to the API
    const mutation = {
      'query': 'mutation users($name: String!) { insert_users(objects: [{name: $name}]) { affected_rows } }',
      'variables': { name: text}
    };
    await fetch(mutation);
    // revalidate
    trigger(mutation);
    setText('')
  }
  return ...
}
```

Once the mutation is complete, we revalidate it with a trigger.

### GraphQL Subscriptions

Finally for subscriptions with realtime data, we have a custom wrapper defined in libs. Using the native `WebSocket` instance, we are creating an initial message that will be sent to the GraphQL server (containing the payload like headers).

```
const ws = new WebSocket(GRAPHQL_ENDPOINT_WS, "graphql-ws");
const init_msg = {
  type: 'connection_init',
  payload: { headers: headers }
};
```

There's no native Subscription hook with SWR, but we will reuse `useSWR` to call a fetcher that initiates a new WebSocket connection.

### Pre-rendering

All of the above examples assumes that data loading happens on the client side. But if you are building an app which requires pre-rendering for SEO/Caching benefits, then you can pass the pre-fetched data as the initial value to the `initialData` option.

For example:

```
const { data, error } = useSWR(query, getData, { initialData: props.users } );
```

This combined with `getStaticProps` will take care of the pre-rendering of data at the server side.

Source Code - [https://github.com/praveenweb/swr-graphql](https://github.com/praveenweb/swr-graphql)

Do try it out and let us know in the comments on what frontend library you prefer using for data fetching via GraphQL.