Relay - Introduction

"Relay is designed for high performance at any scale."

Relay is a Javascript framework created by Meta (Facebook) for fetching and managing GraphQL data. It differs from some alternatives such as Apollo  Client for having a strict way of working and for those who are facing it for the first time, it's not that clear. For me, the big change of understanding came after reading the Thinking in Relay documentation. Some points that I would like to highlight:

  • I idea of Relay is fetching data for a View Hierarchy;
  • It's a bottom-up approach, where each child informs exactly the piece of data (fragment) that it needs;
  • The child connects the graphQL requirements with its parent component. This works by the parent spreading the child's fragments; (Always on the parent/child level);
  • Relay creates the query for the view hierarchy dynamically with the Compiler.

Example

Consider two components:

  • A parent component StoryScreen.tsx
  • A children component AuthorDetail.tsx

Using the bottom-up approach, first define a graphQL fragment with the data AuthorDetail.tsx will require. In this example, the fields to retrieve from the backend are "name" and "url".

const authorDetailsFragment = graphql`
  fragment AuthorDetails_author on Author {
    name
    photo {
      url
    }
  }
`;
Data required for the component on AuthorDetails.tsx

To use the data from this fragment, use the useFragment() hook.

export const AuthorDetails = (props) => {
  const data = useFragment ( authorDetailsFragment, props.author );
  // ...
}
AuthorDetails.tsx

The useFragment() hook, requires 2 params. The first one is the Fragment Definition, which data this component will use. The second one is the Fragment Reference, a reference from where the data will be read from the store (managed by relay). The result is the data requested.

It's possible to think about a fragment as "part of a type, requested in a query" in this case the fragment on the AuthorDetails.tsx is will be retrieved in the query on the StoryScreen.tsx component, but it could comes from it's parent fragment as well. The root of the View Hierachy is where the query is.

Fragment references are obtained by spreading a fragment from another fragment or query, in this case, the query on the parent component StoryScreen.tsx.

const storyQuery = graphql`
  query StoryQuery($storyID: ID!) {
    story(id: $storyID) {
      title
      author {
        ...AuthorDetails_author
      }
    }
  }
`;
Query definition with children on StoryScreen.tsx

Note: The component should extracts from the frament, just the data it is using. If it have child's, it should spread the childs fragments, and pass the resulting piece of the fragment to the child as parameter. It's the child's duty deal with its own data.

Once all fragments and query in the View Hierarchy are connected, the Relay Compiler generates the query, optimizes it, and generate graphql files in order to perform just one request to the backend with all the data needed for the hieranchy.

The useLazyLoadQuery() hook fetches the data during render;

export const Story = (props) => {
  const data = useLazyLoadQuery(storyQuery, props.storyId);

  return (<>
    <Heading>{data?.story.title}</Heading>
    {data?.story?.author && <AuthorDetails author={data.story.author} />}
  </>);
}
StoryScreen.tsx

The data.story.title is used in the parent component and the data.story.author from the spreed fragment, is passed as a Fragment Reference for the children;

The data.story.author is the second parameter in the useFragment() hook, received as props.author.

export const AuthorDetails = (props) => {
  const data = useFragment ( authorDetailsFragment, props.author );
  return (
  	<Text>{data.name}</Text>
  );
}
AuthorDetails.tsx

Every time the fragment changes, for example, retrieving the "lastName" of the Author, just the children component (AuthorDetails.tsx) will change.

const authorDetailsFragment = graphql`
  fragment AuthorDetails_author on Author {
    name
    lastName
    photo {
      url
    }
  }
`;
Data required for the component on AuthorDetails.tsx

Once changed, the compiler will create new graphql files with the correct data. Be ready for lot graphql files in the git.

For me, undertanding this flow was very important for starting to see how Relay Works and why it is so powerful. My intent was just give an overview, a first step. There is a lot of more to dig in, I hope your jorney with the Relay get easy with this starting point.