JavaScript
Article

React Data Fetching with Relay

By Kev Zettler

React is ushering a new era in front end. Published by Facebook, it has rapidly become a popular library used in production by many technology companies. In this article, we’re going to discuss a new complementary React framework called Relay.

The Problem with Data Fetching in React

As React has grown in popularity, the scale and complexity of the projects built with React has grown along with it. React is primarily a view layer library. This has caused some teams to hit unknown territory or limitations while building projects that require a different infrastructure. Facebook has been proactive in offering support and guidance during these growing pains.

Flux

One of the early growing pains for developers using React was event handling. Facebook responded to this issue by publishing Flux, which is an abstract pattern that encouraged unidirectional data flow for handling events in React.

I’ll assume some familiarity with Flux, so I won’t discuss the details of it in this article. In case you aren’t familiar with this topic, you can give a reading to this article by Sandeep Panda or take a look at this page about Flux.

Flux has taken the React ecosystem to the next level. As developers started to get more familiar with Flux, some issues emerged. Flux has been great for managing data as application state, but populating the initial state into an application has been a source of friction.

There are several challenges surrounding Flux’s data initialization. Do stores call the server and populate themselves? Do we use rehydrate methods from the dispatcher? Do we call a bunch of actions on the server to populate the stores? How do we do this asynchronously and load all our data on the server in an isomorphic app before returning a response?

What Is Relay?

Relay is a new React Data fetching framework published by Facebook. Relay aims to provide a clear solution to all of these data-fetching problems.

Relay has a few main selling points:

  • Declarative: This is also a main feature of React. Relay leverage a declarative code style definition for data dependencies, which is very similar to how view components are defined. This is a refreshing change from traditional imperative data-fetching APIs.

  • Collocation: Data dependency definitions live alongside component definitions, which makes it much easier to reason about what data a UI component requires to render. This makes troubleshooting a project’s code a lot easier. Looking at a file that contains a React component definition, it’s immediately obvious what data it needs to function.

  • Mutations: Mutations enable an experience of seamless modification to data which a React view is subscribed to and also populates those modifications to the data persistence layer.

Relay vs Flux

Flux is an abstract idea whereas Relay is an implementation inspired by that idea. Relay is built on the concepts of Flux and has the same concepts of dispatcher, actions, and stores, but they are represented a bit differently. Relay has a new concept called ‘Higher Order Components’ and we’ll expand on this topic in the remainder of the article.

More from this author

At this stage, it’s still unclear if Relay will replace or coincide with existing Flux implementations. For example, Redux, a popular Flux implementation, also leverage ‘Higher Order Components’. Trying to use both Redux and Relay will cause a conflict over which framework is bound to a UI component. There is currently an ongoing discussion regarding Redux’s relationship with Relay.

Higher Order Components

Higher Order components or HOCs are defined in the same way as regular React components. HOCs wrap child UI components. The HOC will execute its queries and then render the child UI component, passing the query data in as props. The Flux flow is now managed by the HOC and the latter will act as a dispatcher. It has methods like setQueryParams() that can be considered as a Flux action. Calling setQueryParams() triggers the Flux flow. The queries defined in the HOC are updated, new data is fetched and the data is persisted in the HOC. The HOC is acting as a Flux store by persisting this data.

Below is a simplified example of a ProfilePicture component and a complimentary HOC. Imagine that we have ProfilePicture defined to render user avatars throughout our project. We need to fetch the data to display the user avatar. We then create a Relay HOC to query the user profile pictures from a database. The HOC passes this query data to the child ProfilePicture component:

class ProfilePicture extends React.Component {
  // A standard Profile Picture component
}

// This is our Higher Order Component. It fetches the data to pass
// as props to Profile Picture
module.exports = Relay.createContainer(ProfilePicture, {
  fragments: {
    user: () => Relay.QL`
      fragment on User {
        profilePicture(size: $size) {
          uri,
        },
      }
    `,
  },
});

Our ProfilePicture component will then get some new local functions passed in as props. This essentially is how Relay triggers the Flux flow. The component calls these Relay prop functions, which is equivalent to a Flux action call. This causes Relay to fetch the latest data requested. Once done it populates its internal store and passes that down to the HOC’s child view component as props.

GraphQL

The above example may look a bit strange, particularly this part:

Relay.QL`
      fragment on User {
        profilePicture(size: $size) {
          uri,
        },
      }
    `,

Much of the magic behind Relay is powered by GraphQL. GraphQL is a new query language from Facebook that specializes in operating on graph data structures. Discussing GraphQL in depth is outside the scope of this article, however you can deepen this topic by reading the Relay documentation which covers it. An existing project will not be set up to work with GraphQL right out of the box. The first recommended steps to getting started with Relay are:

  1. Create a GraphQL Schema
  2. Create a GraphQL Server

It should be noted that it may take a considerable amount of work to convert an existing project to a GraphQL Schema and set up or modify an existing server to be GraphQL-friendly. When starting a project from scratch, it might make more sense to use Relay immediately. Facebook provides a Relay Starter Kit that looks like a great solution for getting up and running with Relay and GraphQL on a new project.

Relay Without GraphQL

With all of the extra overhead required to set up GraphQL, Facebook’s Relay might not be the right tool for existing projects. Luckily, there is another Relay-inspired library out there that may be a better fit for these projects called react-transmit. react-transmit is an open source project that aims to be a “Relay-inspired library based on Promises instead of GraphQL.”

If we update the profile example from above to use react-trasmit then we have the following code:

// Import Transmit
import Transmit from "react-transmit";

class ProfilePicture extends React.Component {
  // A standard Profile Picture component
}

// This is our Higher Order Component. It fetches the data to pass
// as props to Profile Picture
Transmit.createContainer(ProfilePicture, {
  fragments: {
    user: (userId) => {
      return new Promise(function(resolve, reject) { 
          // Do some Ajax here and resolve the promise
      });
    }
  },
});

The react-transmit example looks very similar to the Relay example. However, in this instance the user fragment is now a function that returns a Promise instead of a GraphQL query.

Current State of Relay

Facebook has released an open source “technical preview” of Relay. They have some great examples in the repository that show how to work with Relay and a very detailed documentation section.

It doesn’t seem that Relay is suitable for isomorphic applications at this time. There is no way to tell Relay to wait until all of the data dependencies have been loaded before rendering its child view, something that is needed on the server. In case you’re interested, there is an ongoing discussion regarding how Relay will work on the server. At the moment, this is a pattern that react-transmit is more suited to at the current time.

As for Relay’s future, its roadmap aims to provide a few key features soon:

  • Adapters for other data storage types so there is no hard dependency on GraphQL.
  • Better isomorphic support, as discussed earlier.

Conclusions

In this article, we’ve discussed a new React complementary framework called Relay. Relay is built on some of the same concepts of Flux and powered by GraphQL. As I mentioned, Relay might not be a good choice for already existing projects. However, this framework is quite new and I expect it to become better and better at every release.

Now, it’s your turn. Did you know Relay? Have you ever adopted it in one of your projects?

  • https://franciskim.co Francis Kim

    Didn’t even know about Relay – thanks for this.

  • http://danjavia.xyz Danjavia

    Can you Make an Example unsing React-router too as a blog.

Recommended

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!

Get the latest in JavaScript, once a week, for free.