Give it 5 days - Facebook Relay and GraphQL

Relay schema screenshot
Relay schema screenshot

Me and Alex Savin have been rebuilding Red Badger's blog with Relay and GraphQL. Relay is a front end Javascript framework that works with React to consume a backend GraphQL server. Relay deals with querying a GraphQL server and passing the data to your React components as props. And making mutations on the server while giving you optimistic update and error handling capabilities. But it will soon also be handing in-memory/client state and isomorphic universal app features. Then it will become a competitor with Flux, Redux and Red Badgers Arch. Furthermore a React / React Native / Relay / GraphQL set up could become all you need to deliver the ultimate single page web, iOS and Android app.

A blog by Basecamp co-founder Jason Fried called “Give it 5 minutes” was referenced in the React docs when it came out because React challenges conventional wisdom such as having HTML in your JS. Unfortunely with GraphQL and Relay it’s more like give it 5 days. There is a lot to learn and some of the example code is long in comparison to the short neat examples we saw with React. But power through and you will see the light of Relay and GraphQL. However do bare in mind the libraries are young and there will be some time consuming and confusing error messages along the way.

The libraries

Before Relay came out we only had one library to play with which was graphql/graphql-js. I wrote a blog on this library where I made a GraphQL sever for querying data on any movie in The Open Movie Database. Now since Relay came out on August the 11th we have 3 more libraries to play with!

  1. graphql/graphql-relay-js - A small library to help us construct a graphql-js schema supporting Relay. There are 3 core assumptions Relay make about your GraphQL schema. You can think of these as additional specs to the pure GraphQL specification.
  2. graphql/express-graphql - Express middleware that makes it easier to create an endpoint that will receive a GraphQL queries. It accepts queries via a HTTP POST or GET and returns a JSON response.
  3. facebook/relay - the Relay library itself which runs in the clients browser with React

And fortunately relayjs/relay-starter-kit which ties React and all four of the above libraries together to help us get going quickly. Also if you want to play with example Relay apps check out the 3 official Facebook ones in the example folder in the Relay repo. And the very recently released utility library graphql/graphiql is absolutely sick, it's a React component that lets us render an in-browser GraphQL IDE to test out our GraphQL server.

The magic

Native app speeds with caching - no need to refetch the same node attributes again over the network!

When you visit our /blog index page our SPA application using Relay & React Router (great blog post about doing this here), Relay makes a GraphQL network request asking for 15 posts and a small subset of the post fields(aka attributes) we need to render the multiple PostPreview components. These fields are specified in the PostPreview's Relay container. For example it asks for the title and the published at date but not the posts body. Now what's cool is when you click on the post and view the actual post page, Relay makes another request this time asking for more Post attributes such as the body. But this time it does not ask for the attributes Relay already has in it's store, even though the Post Relay container specifies them. This is because a Post in our GraphQL schema implements the node interface and has a globally unique id which Relay asks for and uses as a key in it's cache. Overall this is nice feature we get for free that makes our app more performant and gives us native navigation speeds! 

Continuous scrolling made easy

One of Relays features is it declarative like React. Watch here how I declare the post's index page displays 15 posts initially, then fetch 5 more when the user gets to the bottom of the page. Furthermore I use React's setState(function|object nextState[, function callback]) and Relay's setVariables([partialVariables: Object, [onReadyStateChange: Function]]) callbacks to display a loading message to the user! Very easy to do!

[gist id="73f1e901e43c27898af5" file="PostIndex.js"]

It lets your front end developers move faster

A GraphQL/Relay set up separates your back and front end team and allows your front end developers to move fast and provide awesome UX. When a view needs an extra attribute you simply add it to your components fragment and your done. No need to make changes to traditional ad-hoc backend server endpoints.  

We are hope to open source our Relay blog soon so people can reuse it! Cheers.