Lang
Blog

Relay Hooks- Facebook’s Newly Improved React-Hooks-Based APIs for Relay

ByPayal Mittal
June 30th . 5 min read
Relay Hooks- Facebook’s Newly Improved React-Hooks-Based APIs for Relay

Created by Robert Balicki & Juan Tejada, the Relay Team at Facebook recently released a new set of APIs, called Relay Hooks, for better fetching and management of GraphQL data.

React-hooks-based APIs enable developers to fetch and manage GraphQL data in React applications by leveraging the Relay framework.

Relay is a structured and opinionated JavaScript framework used to build data-driven React applications backed by GraphQL.

Basically, the Relay hooks use React.js with Relay and improve the existing container-based APIs. These relay hook-APIs provide an upper hand for developers while working with graphql data and come in handy to simplify the development process which would otherwise take a lot of extra time and code. The hooks APIs conveniently reduce the code amount by doing the same job within fewer lines of code.

Relay hooks include APIs for multiple purposes such as pagination, fetching queries, loading data with fragments, mutations, re-fetching, and subscriptions.

These newly updated hooks-based APIs are fully compatible with the existing APIs. You can easily migrate the existing containers to the new APIs if you want but you don’t need to as the container code wo

Facebook team explains that-

Although the hooks-based APIs are new but not untested. In fact, the Facebook website was rewritten from scratch with Relay Hooks. The APIs were written in close association with team React bearing the future of React.js in mind. However, Relay still has a long way to go to become as easygoing and popular as we would like but this new release has greatly improved the relay developer experience.

Why Use Relay Hooks??

Relay Hooks are convenient to use and offer sizable advantages and features, namely-

  • A better experience for re-fetching and pagination processes.
  • Full compatibility with React Strict mode
  • These Relay hooks-APIs power the new, rewritten Facebook, and therefore are tested.
  • New compiler features to automate error-prone tasks.
  • Improved type safety with greater coverage.
  • Lower experienced latency by fetching data before the component renders (using React Suspense) and facilitating data to be displayed to the users more quickly. This prefetching was not possible in the older container-based APIs.
  • Fewer lines of code than the equivalent container-based code
  • Complete Flow and Typescript coverage
  • Configuration of fetch policy that specifies conditions under which a query should be fulfilled and a network request be sent.

Getting Started with Relay Hooks-

When team Relay released its newest version earlier in March 2021, they introduced a new set of developer-friendly APIs in it.

Let’s first set up the latest version of Relay and then we’ll see how these APIs work.

First of all, you need to make sure that you have installed the newest versions of Relay and React on your device as given below-

yarn add react react-dom react-relay

Now, you can either import Relay Hooks from react-relay module or from react-relay/hooks.

import {graphql, useFragment} from ‘react-relay’; // or ‘react-relay/hooks’// …

Now, let’s understand the basics of each Relay Hook API-

RelayEnvironmentProvider

This component sets a Relay environment to use in React context for the entire application. The environment prop specified by this provider component is later used by other hooks like useLazyLoadQuery or useFragment.

import { RelayEnvironmentProvider } from 'relay-hooks';
ReactDOM.render(
  <RelayEnvironmentProvider environment={modernEnvironment}>
    <AppTodo/>
  </RelayEnvironmentProvider>,
  rootElement,
);

useLazyLoadQuery

This hook uses suspense and facilitates GraphQL query fetching during render.

import { useLazyLoadQuery } from "react-relay/hooks";
useLazyLoadQuery(query, variables, options);

It does not take environment as an argument and reads the environment set in the context instead. It takes three arguments, as given here-

👉query

It passes the specified query using graphql template literal.

👉variables

It contains variable values required to fetch the query.

👉options

It contains the following options objects (optional).

  • fetchPolicy: It controls whether or not to send a network request and determines whether the data cached in the Relay store should be used or not.
  • fetchKey: It can be used to force re-fetching of the current query and variables whenever the component re-renders. In simple words, if the fetchKey differs from the one used during the previous render, both the query and variables are re-fetched.
  • networkCacheConfig: It defines the cache configuration options for the network layer.
  • skip: When passed ‘true’, it entirely skips the query.
  • onComplete: This function is called every time a fetch request gets completed.

The useLazyLoadQuery returns a single data object which contains the query data.

If a network request has been made, the useLazyLoadQuery can suspend the ongoing fetching operation and use Suspense for loading states.

For those who are not familiar with React Suspense, it is a new component that’s been added to the latest version of React. It’s not ready yet and still in the experimental phase. This feature allows you to suspend the ongoing operation and lets your components ‘wait’, for the data to be fetched or an asynchronous task to complete, before rendering.

useQuery

The useQuery hook is used for data fetching and is similar to useLazyLoadQuery except for one thing- it does not use React Suspense.

It enables you to use the hooks without having to migrate your application to the concurrent mode. Like useLazyLoadQuery, it accepts three arguments, i.e., query, variables, and options.

usePreloadedQuery

This relay hook follows and implements the ‘render-as-you-fetch’ pattern (using Suspense) and accesses data fetched by loadQuery or useQueryLoader.

The pattern follows the given steps-

  • First, calls to loadQuery callback (returned from useQueryLoader) which contains the query reference or you can directly call the imported loadQuery to return a query reference.
  • Then, use of the query reference with usePreloadedQuery() in the render method. If the query is still pending then this call will get suspended, throw an error in case of failure, and else, will return the query results.
  • This pattern is further followed by useLazyLoadQuery as it allows data fetching while continuing with render.

The usePreloadedQuery takes the following two arguments-

  • · query- Specifies the Graphql query template literal.

  • · preloadedQueryReference- Contains the query reference attained from useQueryLoader or returned by loadQuery.

The usePreloadedQuery returns a data object which contains data read out from the relay store.

useQueryLoader

This hook loads and retains queries easily and securely. It is designed to work in conjunction with the usePreloadedQuery to implement the ‘render-as-you-fetch’ pattern. It stores the query reference in state form.

It takes an initialQueryRef argument, besides the query argument, which contains an initial PreloadedQuery that is to be dispatched as the initial value of the queryReference, returned by useQueryLoader.

It returns a tuple value containing-

  • queryReference: contains the reference to query or null value.
  • loadQuery: A callback function which when executed, loads a query accessible as queryReference. However, if called during render, it will show an error.
  • disposeQuery: A callback function, when called, sets the queryReference to null and disposes it to be garbage collected.

loadQuery

The loadQuery callback returns query references. However, it is not the most convenient way as it leaks this data to the Relay store unless a .dispose() function called on it.

The return value is highly unstable, therefore, you should try passing the result of a loadQuery() to usePreloadedQuery instead which makes sure that the query reference is disposed of.

It fetches data if passed a query, or both data and query if passed a preloaded request. Both the data and query will be stored inside the relay store.

loadQuery works alongside with usePreloadedQuery to implement the ‘return-as-you-fetch’ pattern (as mentioned earlier). It takes an additional fifth argument called environmentProviderOptions other than the usual ones, i.e., environment, query, variables, and options. The environmentProviderOptions provides options to pass to an environmentProvider.

useFragment

It declares specifications of the data requirements of components needed for rendering and then Relay makes sure that this data gets there.

The useFragment is designed in such a way that it automatically updates the fragment data. For instance, if this data gets updated for a particular user in any way anywhere in the app, the component will re-render with this newly updated data.

It takes two arguments, i.e.,

  • fragment: It specifies the GraphQL fragment
  • fragmentReference: It contains information as to which object instance should the data be read from.

The return value is a data object, specifying which data was read from the store.

usePaginationFragment

The usePaginationFragment renders a fragment using a @connection and paginate over it.

import { usePaginationFragment } from 'relay-hooks';
  • data: An object that contains details about which data has been read from the store.
  • isLoadingNext: A Boolean value indicating whether the pagination request for the next items is in flight.
  • isLoadingPrevious: A Boolean value indicating whether the pagination request for previous items is in flight.
  • hasNext: A Boolean value that signifies whether or not the end of connection reached in ‘forward’ direction. It shows True for the forward direction and False otherwise.
  • hasPrevious: A Boolean value that signifies whether or not the end of connection reached in the ‘backward’ direction. It shows True for backward direction and False otherwise.
  • loadNext- A function that fetches more items in connection in the ‘forward’ direction.
  • loadPrevious: A function that fetches more items in connection in the ‘backward’ direction.
  • refetch: A function that uses a new set of variables to re-fetch the connection fragment.

This is not the end! I’ve covered most of the hooks-APIs but there are a few others that I’ve left, you can check them here.

You can use these Relay Hooks incrementally, which means you can use them for the new code or can migrate some parts of your app as well and it won’t affect the rest of your application.

Hope you found this blog helpful! Don’t leave the page without clapping🙃.

Thanks for reading!

Share:
0
+0