How to think your application with Relay
Tags: react, typescript, graphql, relay
Published: 2021-06-22 23:16:28

## Introduction

### First impression

I didn't have a good first impression about Relay when I've started using it. I found it difficult to understand, verbose to use, and I didn't saw the benefits from it.

Even though I didn't like it, I was part of a team, and as a team we choose to stick with Relay and see in the long term if it was a good choice or not.

As the time goes by, I've started to get along with it and to understand how to use it. I still didn't have the full idea, but just to realize how I could use it to solve simple problems like data fetching, and to know what I was doing was enough for me at the time.

### Responsibilities

Months later, I was promoted to tech lead and with that came the responsibility to understand and to explain to my team why we're using the stuff that we're using. I had a challenge. I needed to understand why we use Relay and not something else.

And I believe that like any other solution, if you don't know how and why you use it, you're going to face the same or even worse problems that you're trying to solve with it.

### This article

This article is a grasp of that process of understanding why we use Relay. I'm going to show you how to think your application using Relay, because I believe that to understand other solutions that Relay provides you need to understand first what problems we have right now.

---

## What's Relay?

It's a JavaScript framework that tries to facilitate the process of fetching data on front-end using `GraphQL`. It's developed by Facebook and was conceived with the same ideia of React componentization.

### React components and Relay

The ideia behind components in React it's to decrease the complexity of your app by dividing it into smaller parts called components. These components are easier to understand and to maintain, and that increases the capability of your app to scale.

> And how does that relates to Relay?

The ideia behind Relay is that you have your data dependencies collocated with your component and that it's beneficial for some reasons:

- It's easier to understand which data is needed for your component to work.
- If your component needs any other data from your server, you don't need to change your entire `query` structure, just your component. (__Not every case works this way, but most of them__)
- It's easier to test your component isolated from your entire structure.

## How to use Relay?

To understand it, let's take that YouTube page below:

![youtube](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oizvd8xunk2wmlsgt8zq.png) 

We can divide it in four components that receive the data from the servers.

- `VideoPlayer`: used to render the video that we're watching. Probably need the `videoSrc` from the server.
- `VideoDetails`: show the video details like _title_, _description_, _author_, _number of likes_ and _dislikes_.
- `RelatedVideos`: it's a list of videos that the YouTube algorithm believes that you would like to see.
- `UserImg`: renders the logged user profile image.

![youtube_components](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aawa0bqst53ytnu7b1n7.jpeg) 

> Just remembering that all of that it's just an example. For sure the real YouTube architecture it's much more complex than this.

With these components in mind, we have two approaches to get the data from the server using Relay.

### 1. Each component fetches the data that it needs

We can draw a diagram like this to represent that solution:

![first-architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0e3zua12qli9dn7u6mh.jpg) 

On the left side, we have a simplified version of the YouTube page. Where each component is represented by a gray circle and they call the server through a `GraphQL` query, like this one:

```GraphQL
graphql`
  query NavbarQuery {
    user {
      profileImg {
        src
      }
    }
  }
`
```

#### Benefits

With this solution, we could show different loading indicators in each part of our application. Something like this:

![linkedin image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jzu5yuh48aar4pvkt00.png) 

By doing that we improve the user experience by not blocking entirely his access to the screen and show which data we're fetching and what we already fetched.

> [Here's an article](https://uxdesign.cc/what-you-should-know-about-skeleton-screens-a820c45a571a) explaining why you should use `loading skeletons` in your interface.

#### Downsides

The first problem is related with the tree architecture where a component depends on another one to render. As an example, let's get just the structure responsible for showing us the video:

![VideoPlayer architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/imr7hc9ilui793zycxao.jpg) 

Here, we're only going to get the data with the `videoSrc` when the component `VideoPlayer` is fully rendered. And if for some reason any of these components above the `VideoPlayer` take a long time to load, we would need to wait that time until we can call the server and start loading the video.

With that we would have two times to load the video:

- rendering the components above the `VideoPlayer`.
- recieving the `response` from the `server` with the `videoSrc` data.

Another problem is that we would end up with a lot of requests to the server, where each one of them will ask **just for a single part of the data**. And it makes sense that once the connection is open with the server, we ask for all the data that we need.

> Ok, so we have these two problems. What it's the alternative?

### 2. The recommended solution

Instead of fetching the data on each component, we fetch them once on the page load, in other words, **every page is a query**.

> But didn't you said that Relay is built on colocating the data dependencies with the components that need them?

Yes, I did. When I said `data dependencies` I didn't mean the fetch function, I mean the declaration of the data that it's needed. We only fetch once, at the page render. It would look like this

![second-architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txhrxv5xzz8w30crmc19.jpg) 

#### Benefits

With that, we ask for all the data that we need to render the page on the page load. This comes with the following benefits:

- We decrease the amount of request made to the server.
- Since we're not waiting for some component to load, we decrease the load time to show relevant data to the user.

#### Colocating the data dependencies with Fragments

In order to colocate the data dependencies of a component close to it, we can use `Relay` `Fragments`.

A `Fragment`, in `Relay`, it's a declaration of the data that a specific component need. 

It's like what we had with every component making a fetch, but instead of a fetch, we're only declaring the data that we need, and the fetch only occurs once. The implementation would look like this:

```graphQL
// page component
graphql`
  query PageQuery {
    user {
      ...NavbarFragment_user
    }
  }
`

// navbar component
graphql`
  fragment NavbarFragment_user on UserType {
    profileImg {
      src
    }
  }
`
```

This way, the `Navbar` declares exactly what it needs and if something change, we will only change on the fragment, not on the page query.

> Even though this is nice, we have a problem :(

#### Downsides

At the version `10` of `Relay` we can't have a `loading indicator` per component, we need to show a `loading indicator` on the entire page before showing some data to the user, something like this:

![full-loading-screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s9p6541nyv60ernabe23.jpg) 

You have two ways to solve this problem.

You could use the first approach to solve this problem, where each component calls a `fetch` and while this `fetch` don't return a response, you show a `loading indicator`.

The other way and the one that I recommend, is to **upgrade your Relay to version 11** and start to use the `@defer` directive from `GraphQL` alongside `Suspense` component from `React`. 

With the `@defer` directive you could say that a specific piece of your `query`, like a `fragment`, should be loaded asynchronously and while the response of that piece doesn't return from the server, you show a `loading indicator` passed to your `Suspense` component.

> [Here's the Relay documentation](https://relay.dev/docs/guided-tour/reusing-cached-data/rendering-partially-cached-data/) where they explain in more details how to do that and in [this video](https://youtu.be/Tl0S7QkxFE4) how they're using that on Facebook.

---

## Conclusion

Just as `React` once was, `Relay` still a not much used library and because of that there's not much articles and tutorials explaining how it works.
I do hope that this article increased your understanding about how to use `Relay` on your application or how its main idea works.

If you missed a more technical explanation, or if you still have some questions that I didn't cover, feel free to [send me a tweet or a DM](https://twitter.com/samuelmpinho) 🤙