React relay graphql tutorial

React relay graphql tutorial DEFAULT



Picking the right data architecture in a client-server web app can be difficult. There are a myriad of decisions to be made when you try to implement a data architecture. For example:

  • How will we fetch data from the server?
  • What do we do if that fetch fails?
  • How do we query dependencies and relationships between data
  • How do we keep data consistent across the app?
  • How can we keep developers from breaking each others' components accidentally?
  • How can we move faster and write our app-specific functionality rather than spending our time pushing data back and forth from our server?

Thankfully, Relay has a theory on all of these issues. Even better: it's an implementation of that theory and it's a joy to use, once you get it set up. But it's natural to ask: What is Relay?

Relay is a library which connects your React components to your API server.

We talked about GraphQL earlier in the book and it may not be immediately clear what the relationship is between Relay, GraphQL, and React. You can think of Relay as the glue between GraphQL and React.

Relay is great because:

  • components declare the data they need to operate
  • it manages how and when we fetch data
  • it intelligently aggregates queries, so we don't fetch more than we need
  • it gives us clear patterns for navigating relationships between our objects and mutating them

One of the most helpful things about Relay that we'll see in this chapter is that the GraphQL queries are co-located with the component. This gives us the benefit of being able to see a clear specification of the values needed to render a component directly alongside the component itself.

Each component specifies what it needs and Relay figures out if there's any duplication, before making the query. Relay will aggregate the queries, process the responses, and then hand back to each component just the data it asked for.

GraphQL can be used independent of Relay. You can, in theory, create a GraphQL server to have more-or-less any schema you want. However, Relay has a specification that your GraphQL server must follow in order to be Relay-compatible. We'll talk about those constraints.

What We're Going to Cover

In this chapter we're going to walk through a practical tutorial on how to setup and use Relay in a client app.

Relay depends on a GraphQL server, which we've provided in the sample code, but we're not going to talk about the implementation details of that server.

In this chapter we're going to:

  • explain the various concepts of Relay
  • describe how to setup Relay in our app (with routing)
  • show how to fetch data from Relay into our components
  • show how to update data on our server using mutations
  • highlight tips and tricks about Relay along the way

By the end of this chapter you'll understand what Relay is, how to use it, and have a firm foundation for integrating Relay into your own apps.

What We're Building

The Client

In this chapter, we're going to build a simple bookstore. We'll have three pages:

  • A book listing page, which shows all of the books we have for sale.

Books Store Page

  • An author bio page, which shows an author's information and the books they've authored.

Author Page

  • A book listing page, which shows a single book and the authors for that book. We'll also edit a book on this page.

Book Listing Page

The data model here is straightforward: a book has (and belongs to) many authors.

This data is provided to our app via an API server.

The Server

We've provided a Relay-compatible GraphQL demo server in the sample code with this app. In this chapter we aren't going to discuss the implementation details of the server. If you're interested in building GraphQL servers, checkout the chapter "GraphQL Server."

This server was created with the library graffiti-mongoose. If you're using MongoDB and mongoose, then is a fantastic choice for adapting your models to GraphQL. takes your models and automatically generates a Relay-compatible GraphQL server.

That said, there are libraries that can help you generate GraphQL from your models for every popular language. Checkout the list awesome-graphql to see what libraries are available.

Try The App

You can find the project for this chapter inside the folder of the code download:

We've included the completed server and completed client. Before we can run them, we need to run on both the client and the server:

Next, you can run them individually in two separate tabs with:

Or we've provided a convenience command that will run them both with:

When they're running, you should be able to access the GraphQL server at and the client app at .

In this chapter, we're going to be spending time in our browser looking at both the client and the server. We've installed the GraphQL GUI tool "GraphiQL" on this demo server.

Relay is based on GraphQL, and so to get a better understanding of how it works, we're going to be running a few queries "by hand" in this GraphiQL interface.

How to Use This Chapter

While we will introduce all of the terminology of Relay, this chapter is intended to be a guide to working with Relay and not the API documentation.

As you're reading this chapter, feel free to cross-reference the official docs to dig in to the details.


This is an advanced chapter. We're going to focus on using Relay and not re-cover the basics of writing React apps. It's assumed that you're somewhat comfortable with writing components, using props, JSX, and loading third party libraries. Relay also requires GraphQL, and so we assume you have some familiarity with GraphQL as well.

If you don't feel comfortable with these things, we cover all of them earlier in the book.

Relay 1

Currently this chapter covers Relay 1.x. There is a new version of Relay in the works, but don't let that stop you from learning Relay 1. There is no public release date and Facebook employee Jaseph Savona stated on GitHub that Relay 2 has "definite API differences, but the core concepts are the same and the API changes serve to make Relay simpler and more predictable"

Some good news here is that the underlying GraphQL specification doesn't change. So while, yes, Relay will have a v2 in the future. We can still use Relay 1 in our production apps today.

If you're interested more in the future of Relay, checkout Relay: State of the State.

Guide to the Code Structure

In this chapter, we've provided the completed version of the app in .

In order to break up the concepts in to more digestible bites, we've broken up some of the components into steps. We've included these intermediate files in .

Our Relay app contains a server, a client, and several build tools -- these all add up to quite a lot of files and directories. Here's a brief overview of some of the directories and files you'll find in our project. (Don't worry if some of this is unfamiliar, we'll explain everything you need to know in this chapter):

Feel free to poke around at the sample code we've provided, but don't worry about understanding every file just yet. We'll cover all of the important parts.

Relay is a Data Architecture

Relay is a JavaScript library that runs on the client-side. You connect Relay to your React components and then Relay will fetch data from your server. Of course, your server also needs to conform to Relay's protocol, and we'll talk about that, too.

Relay is designed to be the data-backbone for your React app. This means that, ideally, we'd use Relay for all of our data loading and for maintaining the central, authoritative state for our application.

Because Relay has its own store it's able to cache data and resolve queries efficiently. If you have two components that are concerned with the same data, Relay will combine the two queries into one and then distribute the appropriate data to each component. This has the duel benefit of minimizing the number of server calls we need but still allowing the individual components the ability to specify locally what data they need.

Because Relay holds a central store of your data, this means it's not really compatible with other data architectures that keep a central store, like Redux. You can't have two central stores of state and so this makes the current versions of Redux and Relay essentially incompatible.


If you're already using Redux but you'd like to try Relay, there's still hope: the Apollo project is a Relay-inspired library that is based on Redux. If you're careful, you can retrofit Apollo into your existing Redux app.

We're not going to talk about Apollo in this chapter, but it's a fantastic library and it's absolutely worth looking into for your app.

Relay GraphQL Conventions

One thing we need to clarify is the relationship between Relay and GraphQL.

Our GraphQL server defines our GraphQL schema and how to resolve queries against that schema. GraphQL itself lets you define a wide variety of schemas. For the most part, it doesn't dictate what the structure of your schema should be.

Relay defines a set of conventions on top of GraphQL. In order to use Relay, your GraphQL server must adhere to a specific set of guidelines.

At a high level, these conventions are:

  1. A way to fetch any object by ID (regardless of type)
  2. A way to traverse relationships between objects (called "connections") with pagination
  3. A structure around changing data with mutations

These three requirements allow us to build sophisticated, efficient apps. In this chapter, we'll make these generic guidelines concrete.

Let's explore implementations of these three Relay conventions directly on our GraphQL server. Then later in the chapter we'll implement them in our client app.

Relay Specification Official Docs

You can checkout Facebook's Official Documentation on the Relay/GraphQL specification here

Exploring Relay Conventions in GraphQL

Make sure you have the GraphQL server running, as described above, and open it in your browser at the address .

Remember that GraphiQL reads our schema and provides a documentation explorer to navigate the types. Click on the "Docs" link in GraphiQL to show the "Root Types" of our schema.

GraphiQL Interface with Docs

Fetching Objects By ID

In our server we have two models: and . The first thing we're going to do is look-up a specific object by ID.

Imagine that we want to create a page that shows the information about a particular author. We might have a URL such as , where is the ID of the author. We'd want Relay to ask our server "what is the information for the author ?" In that case, we'd use a GraphQL query like we're going to define below.

However, we have a bit of a chicken and egg problem at the moment: we don't know the IDs of any individual record.

So let's load the entire list of authors' s and s and then take note of one of the IDs.

Enter the following query into GraphiQL:

And click the play button:

GraphiQL Authors with IDs

Now that we have an author ID, we can query to get the author with a specific id:



While this is handy, from the query we can only receive an object of type , so it doesn't fulfill the requirement of the Relay specification. The Relay specification says that we need to have a way to query any object () via the query.



In this tutorial, we will build a game using GraphQL mutations. The goal of the game is to find a hidden treasure in a grid of 9 squares. We will give players three tries to find the treasure. This should give us an end-to-end look at Relay – from the GraphQL schema on the server, to the React application on the client.

Warm up #

Let's start a project using the Relay Starter Kit as a base.

git clone relay-treasurehunt cd relay-treasurehunt npm install

A simple database #

We need a place to hide our treasure, a way to check hiding spots for treasure, and a way to track our turns remaining. For the purposes of this tutorial, we'll hide these data in memory.

exportclassGame{}exportclassHidingSpot{}var game =newGame(); ='1';var hidingSpots =[];(function(){var hidingSpot;var indexOfSpotWithTreasure = Math.floor(Math.random()*9);for(var i =0; i <9; i++){ hidingSpot =newHidingSpot(); =`${i}`; hidingSpot.hasTreasure =(i === indexOfSpotWithTreasure); hidingSpot.hasBeenChecked =false; hidingSpots.push(hidingSpot);}})();var turnsRemaining =3;exportfunctioncheckHidingSpotForTreasure(id){if(hidingSpots.some(hs => hs.hasTreasure && hs.hasBeenChecked)){return;} turnsRemaining--;var hidingSpot =getHidingSpot(id); hidingSpot.hasBeenChecked =true;};exportfunctiongetHidingSpot(id){return hidingSpots.find(hs => === id)}exportfunctiongetGame(){return game;}exportfunctiongetHidingSpots(){return hidingSpots;}exportfunctiongetTurnsRemaining(){return turnsRemaining;}

What we have written here is a mock database interface. We can imagine hooking this up to a real database, but for now let's move on.

Authoring a schema #

A GraphQL schema describes your data model, and provides a GraphQL server with an associated set of resolve methods that know how to fetch data. We will use graphql-js and graphql-relay-js to build our schema.

Let's open up the starter kit's schema, and replace the database imports with the ones we just created:

import{ Game, HidingSpot, checkHidingSpotForTreasure, getGame, getHidingSpot, getHidingSpots, getTurnsRemaining,}from'./database';

At this point, you can delete everything up until in .

Next, let's define a node interface and type. We need only provide a way for Relay to map from an object to the GraphQL type associated with that object, and from a global ID to the object it points to:

var{nodeInterface, nodeField}=nodeDefinitions((globalId)=>{var{type, id}=fromGlobalId(globalId);if(type ==='Game'){returngetGame(id);}elseif(type ==='HidingSpot'){returngetHidingSpot(id);}else{returnnull;}},(obj)=>{if(obj instanceofGame){return gameType;}elseif(obj instanceofHidingSpot){return hidingSpotType;}else{returnnull;}});

Next, let's define our game and hiding spot types, and the fields that are available on each.

var gameType =newGraphQLObjectType({ name:'Game', description:'A treasure search game', fields:()=>({ id:globalIdField('Game'), hidingSpots:{ type: hidingSpotConnection, description:'Places where treasure might be hidden', args: connectionArgs, resolve:(game, args)=>connectionFromArray(getHidingSpots(), args),}, turnsRemaining:{ type: GraphQLInt, description:'The number of turns a player has left to find the treasure', resolve:()=>getTurnsRemaining(),},}), interfaces:[nodeInterface],});var hidingSpotType =newGraphQLObjectType({ name:'HidingSpot', description:'A place where you might find treasure', fields:()=>({ id:globalIdField('HidingSpot'), hasBeenChecked:{ type: GraphQLBoolean, description:'True if this spot has already been checked for treasure', resolve:(hidingSpot)=> hidingSpot.hasBeenChecked,}, hasTreasure:{ type: GraphQLBoolean, description:'True if this hiding spot holds treasure', resolve:(hidingSpot)=>{if(hidingSpot.hasBeenChecked){return hidingSpot.hasTreasure;}else{returnnull;}},},}), interfaces:[nodeInterface],});

Since one game can have many hiding spots, we need to create a connection that we can use to link them together.

var{connectionType: hidingSpotConnection}=connectionDefinitions({name:'HidingSpot', nodeType: hidingSpotType});

Now let's associate these types with the root query type.

var queryType =newGraphQLObjectType({ name:'Query', fields:()=>({ node: nodeField, game:{ type: gameType, resolve:()=>getGame(),},}),});

With the queries out of the way, let's start in on our only mutation: the one that spends a turn by checking a spot for treasure. Here, we define the input to the mutation (the id of a spot to check for treasure) and a list of all of the possible fields that the client might want updates about after the mutation has taken place. Finally, we implement a method that performs the underlying mutation.

var CheckHidingSpotForTreasureMutation =mutationWithClientMutationId({ name:'CheckHidingSpotForTreasure', inputFields:{ id:{ type:newGraphQLNonNull(GraphQLID)},}, outputFields:{ hidingSpot:{ type: hidingSpotType, resolve:({localHidingSpotId})=>getHidingSpot(localHidingSpotId),}, game:{ type: gameType, resolve:()=>getGame(),},}, mutateAndGetPayload:({id})=>{var localHidingSpotId =fromGlobalId(id).id;checkHidingSpotForTreasure(localHidingSpotId);return{localHidingSpotId};},});

Let's associate the mutation we just created with the root mutation type:

var mutationType =newGraphQLObjectType({ name:'Mutation', fields:()=>({ checkHidingSpotForTreasure: CheckHidingSpotForTreasureMutation,}),});

Finally, we construct our schema (whose starting query type is the query type we defined above) and export it.

exportvar Schema =newGraphQLSchema({ query: queryType, mutation: mutationType });

Processing the schema #

Before going any further, we need to serialize our executable schema to JSON for use by the Relay.QL transpiler, then start up the server. From the command line:

npm run update-schema npm start

Writing the game #

Let's tweak the file to anchor our game to the root field of the schema:

exportdefaultclassextends Relay.Route {static path ='/';static queries ={ game:()=> Relay.QL`query { game }`,};static routeName ='AppHomeRoute';}

Next, let's create a file in and create subclass of called to hold our mutation implementation:

import Relay from'react-relay';exportdefaultclassCheckHidingSpotForTreasureMutationextendsRelay.Mutation{static fragments ={ game:()=> Relay.QL` fragment on Game { id, turnsRemaining, } `, hidingSpot:()=> Relay.QL` fragment on HidingSpot { id, } `,};getMutation(){return Relay.QL`mutation{checkHidingSpotForTreasure}`;}getCollisionKey(){return`check_${}`;}getFatQuery(){return Relay.QL` fragment on CheckHidingSpotForTreasurePayload { hidingSpot { hasBeenChecked, hasTreasure, }, game { turnsRemaining, }, } `;}getConfigs(){return[{ type:'FIELDS_CHANGE', fieldIDs:{,,},}];}getVariables(){return{,};}getOptimisticResponse(){return{ game:{ -1,}, hidingSpot:{, hasBeenChecked:true,},};}}

Finally, let's tie it all together in :

import CheckHidingSpotForTreasureMutation from'../mutations/CheckHidingSpotForTreasureMutation';classAppextendsReact.Component{_getHidingSpotStyle(hidingSpot){var color;if(this.props.relay.hasOptimisticUpdate(hidingSpot)){ color ='lightGrey';}elseif(hidingSpot.hasBeenChecked){if(hidingSpot.hasTreasure){ color ='blue';}else{ color ='red';}}else{ color ='black';}return{ backgroundColor: color, cursor:this._isGameOver()?null:'pointer', display:'inline-block', height:100, marginRight:10, width:100,};}_handleHidingSpotClick(hidingSpot){if(this._isGameOver()){return;} Relay.Store.commitUpdate(newCheckHidingSpotForTreasureMutation({, hidingSpot,}));}_hasFoundTreasure(){return( => edge.node.hasTreasure));}_isGameOver(){return! ||this._hasFoundTreasure();}renderGameBoard(){ =>{return(<div key={} onClick={this._handleHidingSpotClick.bind(this, edge.node)} style={this._getHidingSpotStyle(edge.node)}/>);});}render(){var headerText;if(this.props.relay.getPendingTransactions({ headerText ='\u2026';}elseif(this._hasFoundTreasure()){ headerText ='You win!';}elseif(this._isGameOver()){ headerText ='Game over!';}else{ headerText ='Find the treasure!';}return(<div><h1>{headerText}</h1>{this.renderGameBoard()}<p>Turns remaining:{}</p></div>);}}exportdefault Relay.createContainer(App,{ fragments:{ game:()=> Relay.QL` fragment on Game { turnsRemaining,hidingSpots(first:9){ edges { node { hasBeenChecked, hasTreasure, id, ${CheckHidingSpotForTreasureMutation.getFragment('hidingSpot')},}}}, ${CheckHidingSpotForTreasureMutation.getFragment('game')},} `,},});

A working copy of the treasure hunt can be found under the directory in the Relay repository.

Now that we've gone through this tutorial, let's dive into what it means to build a GraphQL client framework and how this compares to clients for more traditional REST systems.

Next →

  1. Yamaha snowmobile 2020
  2. Weiss rwby volume 7
  3. Everbilt insert nut
  4. Pof fake accounts

Getting Started


Since this is a frontend track, we don’t want to spend too much time setting up the backend. This is why we use Graphcool, a service that provides a production-ready GraphQL API out-of-the-box.

The Data Model

You’ll use the Graphcool CLI to generate the server based on the data model that we need for the app. Speaking of the data model, here is what the final version of it looks like written in the GraphQL Schema Definition Language (SDL):

Creating the GraphQL Server

The first thing you need to do is install the Graphcool CLI with npm.

NOTE: This tutorial uses the legacy version of Graphcool and will be updated soon to use the new Graphcool Framework. The CLI commands mentioned in tutorial are outdated, you can read more about the new CLI here. If you still want to go through this tutorial, you can install the old version of the CLI using .

Now you can go and create the server.

This will execute the command with two arguments:

  • : This option accepts a -schema that’s either stored locally or at a remote URL. In your case, you’re using the schema stored at, we’ll take a look at it in a bit.
  • : This is the name of the Graphcool project you’re creating, here you’re simply calling it .

Note that this command will open up a browser window first and ask you to authenticate on the Graphcool platform.

The schema that’s stored at is identical to the one that you just saw.

Once the project was created, you’ll find the Graphcool Project File () in the directory where you executed the command. It should look similar to this:

The top of the file contains some metadata about the project, namely the project ID and the version number of the schema.

The and types are generated by Graphcool and have some special characteristics. can be used for authentication and for file management.

Also notice that each type has three fields called , and . These are managed by the system and read-only for you.

Populate The Database & GraphQL Playgrounds

Before you move on to setup the frontend, go ahead and create some initial data in the project so you’ve got something to see once you start rendering data in the app!

You’ll do this by using a GraphQL Playground which is an interactive environment that allows you to send queries and mutations. It’s a great way to explore the capabilities of an API.

This command will read the project ID from the project file and open up a GraphQL Playground for that project in a browser.

The left pane of the Playground is the editor that you can use to write your queries and mutations (and even subscriptions). Once you click the play button in the middle, the response to the request will be displayed in the results pane on the right.

Since you’re adding two mutations to the editor at once, the mutations need to have operation names. In your case, these are and .

Click the Play button

This creates two new records in the database. You can verify that the mutations actually worked by either viewing the currently stored data in the data browser (simply click DATA in the left side-menu) or by sending the following query in the already open Playground:

If everything wen well, the query will return the following data:


Creating the App

Next, you are going to create the React project! As mentioned in the beginning, you’ll use for that.

This will create a new directory called that has all the basic configuration setup.

Make sure everything works by navigating into the directory and starting the app:

This will open a browser and navigate to where the app is running. If everything went well, you’ll see the following:

Navigating to localhost:3000

Your project structure should now look as follows:

Prepare Styling

This tutorial is about the concepts of GraphQL and how you can use it from within a React application with Relay, so we want to spend the least time on styling issues. To ease up usage of CSS in this project, you’ll use the Tachyons library which provides a number of CSS classes.

Since we still want to have a bit more custom styling here and there, we also prepared some styles for you that you need to include in the project.

Installing Relay Dependencies

Next, you need to pull in the functionality of Relay into your project. In particular, there are three dependencies you need to install:

  1. : Contains major functionality of the Relay runtime and is responsible for all networking and caching tasks.
  2. : The Relay Compiler is a tool you’ll use at build time to validate and optimize the GraphQL code you’re writing in the project. Read more about it in the official docs.
  3. : Relay leverages a Babel plugin to transform the GraphQL code you write in a project and bring it into the right format for the Relay Compiler. Read more about it in the official docs.

Here is high-level overview on the architecture used for Relay Modern.

Eject from to configure Babel

hides all the build tooling configurations from you and provides a comfortable spot for starting out. However, in your case you actually need to do some custom Babel configurations to get Relay to work. So you need to eject from .

This command essentially opens up the blackbox that was handed to you by and let’s you do the build configuration yourself. In this case, you need to add the that you installed in the previous step to the build process.

That’s it already for the Babel configuration. Set up the Relay in the app next!

Creating the Relay

The Relay Environment provides the core of the Relay functionality at runtime by ”[bundling] together the configuration, cache storage, and network-handling that Relay needs in order to operate.”

A Relay Environment needs to be instantiated with two major components:

  1. A that knows which GraphQL server it can talk to
  2. A that takes care of the caching

This code has been taken from the example in the docs and was only slightly customised.

Let’s quickly discuss the commented sections to understand better what’s going on:

  1. You first import the required JS modules that you need to instantiate and configure the .
  2. Here you instantiate the required that will store the cached data.
  3. Now you create a that knows your GraphQL server from before, it’s instantiated with a function that returns a of a networking call to the GraphQL API - here that’s done using .
  4. The needs to know the server endpoint for your API. In the next step, you’ll replace the placeholder with your actual endpoint.
  5. With the and available you can instantiate the actual .
  6. Lastly you need to export the from this module.

There are two ways for you to get your endpoint. You can either open the Graphcool Console and click the Endoints-button in the bottom-left corner. The second option is to use the CLI which is what you’ll do now.

This command will display four different endpoints that each have a specific purpose. Since you’re using Relay in this tutorial, you need to use the endpoint for the .

Note: All endpoints follow a similar structure in that there is a fixed portion of the URL and the last part is the ID of your project. For the , the structure looks as follows:

Downloading the Schema

Before you can start using Relay, you’ll need to download the full GraphQL schema into your project and make it available to the Relay Compiler.

Note: There is a difference between the GraphQL schema that you saw above and a full GraphQL schema. The full schema is required for every GraphQL server since it defines all capabilities of the API by spelling out the and types. However, when using Graphcool, you only define a subset of this schema, namely the types of your data model. The rest of the schema that represents the actual API will then be generated for you.

You’ll download the schema using a tool called .

Next, you need to use the endpoint for the Relay API again since that’s where will download the schema from.

Notice that the in the this command means that the output of will be written to a new file called . This file needs to be placed into the root directory of your project, so the project structure should now look as follows:

That’s it, you’re all set to start loading some data into your app! 🚀

ToEatApp React-Relay-GraphQL Tutorial - Application Setup



NOTE: This tutorial uses the legacy version of Graphcool and will be updated soon to use the new Graphcool Framework. The CLI commands mentioned in tutorial are outdated, you can read more about the new CLI here. If you still want to go through this tutorial, you can install the old version of the CLI using .

In the previous chapter, you learned about major concepts and benefits of GraphQL. Now is the time to get your hands dirty and start out with an actual project!

You’re going to build a simple clone of Hackernews. Here’s a list of the features the app will have:

  • Display a list of links
  • Users can authenticate
  • Authenticated users can create new links
  • Authenticated users can upvote links (one vote per link and user)
  • Realtime updates when other users upvote a link or create a new one

In this track, you’ll use the following technologies for building the app:

  • Frontend:

    • React: Frontend framework for building user interfaces
    • Relay: Powerful GraphQL client developed by Facebook, heavily optimized for performance
  • Backend:

    • Graphcool: Flexible backend platform combining GraphQL + Serverless

You’ll create the React project with , a popular command-line tool that gives you a blank project with all required build configuration already setup.

Why a GraphQL Client?

In the Clients section in the GraphQL part, we already covered the responsibilities of a GraphQL client on a higher level, now it’s time to get bit more concrete.

In short, you should use a GraphQL client for tasks that are repetitive and agnostic to the app you’re building. For example, being able to send queries and mutations without having to worry about lower-level networking details or maintaining a local cache. This is functionality that you’ll want in any frontend application that’s talking to a GraphQL server - why build it yourself if you can use one of the amazing GraphQL clients out there?

There are a few GraphQL client libraries available, that all give you varying degrees of control over ongoing GraphQL operations and come with various different benefits and drawbacks. For very simple use cases (such as writing scripts), might already be enough for your needs. Libraries like it are thin layers around sending HTTP requests to your GraphQL API.

Chances are that you’re writing a somewhat larger application where you want to benefit from caching, optimistic UI updates and other handy features. In these cases you’ll likely want to use a full GraphQL client that handles the lifecycle of all your GraphQL operations. You have the choice between Relay, Apollo Client, and urql.

Apollo vs Relay vs urql

The most common question heard from people that are getting started with GraphQL on the frontend is which GraphQL client they should use. We’ll try to provide a few hints that’ll help you decide which of these clients is the right one for your next project!

Relay is Facebook’s homegrown GraphQL client that they open-sourced alongside GraphQL in 2015. It incorporates all the learnings that Facebook gathered since they started using GraphQL in 2012. Relay is heavily optimized for performance and tries to reduce network traffic where possible. An interesting side-note is that Relay itself actually started out as a routing framework that eventually got combined with data loading responsibilities. It thus evolved into a powerful data management solution that can be used in JavaScript apps to interface with GraphQL APIs.

The performance benefits of Relay come at the cost of a notable learning curve. Relay is a pretty complex framework and understanding all its bits and pieces does require some time to really get into it. The overall situation in that respect has improved with the release of the 1.0 version, called Relay Modern, but if you’re looking for something to just get started with GraphQL, Relay might not be the right choice just yet.

Apollo Client is a community-driven effort to build an easy-to-understand, flexible and powerful GraphQL client. Apollo has the ambition to build one library for every major development platform that people use to build web and mobile applications. Right now there is a JavaScript client with bindings for popular frameworks like React, Angular, Ember or Vue as well as early versions of iOS and Android clients. Apollo is production-ready and has handy features like caching, optimistic UI, subscription support and many more.

urql is a more dynamic approach on GraphQL clients and a newer project compared to Relay and Apollo. While it’s highly focused on React, at its core it focuses on simplicity and extensibility. It comes with the barebones to build an efficient GraphQL client, but gives you full control over how it processes GraphQL operations and results via “Exchanges”. Together with the first-party exchange it is basically equivalent in functionality with Apollo, but with a smaller footprint and a very focused API.


Graphql tutorial relay react

Step-by-step Guide

Relay is a framework for managing and declaratively fetching GraphQL data. It allows developers to declare what data each component needs via GraphQL, and then aggregate these dependencies and efficiently fetch the data in fewer round trips. In this guide we'll introduce the key concepts for using Relay in a React app one at a time.

Step 1: Create React App#

For this example we'll start with a standard install of Create React App. Create React App makes it easy to get a fully configured React app up and running and also supports configuring Relay. To get started, create a new app with:

At this point we should be able to change to the app's directory and run it:

For troubleshooting and more setup options, see the Create React App documentation.

Step 2: Fetch GraphQL (without Relay)#

If you're exploring using GraphQL with Relay, we highly recommend starting with a basic approach and using as few libraries as possible. GraphQL servers can generally be accessed using plain-old HTTP requests, so we can use the API to request some data from our server. For this guide we'll use GitHub's GraphQL API as the server, but if you already have a GraphQL server feel free to use that instead.

2.1: GitHub GraphQL Authentication#

To start we'll need an authentication token for the GitHub API (if you're using your own GraphQL endpoint, you can skip this step):

  • Open
  • Ensure that at least the scope is selected.
  • Generate a token
  • Create a file and add the following contents, replacing with your authentication token:

2.2: A fetchGraphQL Helper#

Next let's update the home screen of our app to show the name of the Relay repository. We'll start with a common approach to fetching data in React, calling our fetch function after the component mounts (note: later we'll see some limitations of this approach and a better alternative that works with React Concurrent Mode and Suspense). First we'll create a helper function to load data from the server. Again, this example will use the GitHub API, but feel free to replace it with the appropriate URL and authentication mechanism for your own GraphQL server:

2.3: Fetching GraphQL From React#

Now we can use our function to fetch some data in our app. Open and edit it as follows:

Step 3: When To Use Relay#

At this point we can fetch data with GraphQL and render it with React. This is a reasonable solution that can be sufficient for many apps. However, this approach doesn't necessarily scale. As our app grows in size and complexity, or the number of people working on the app grows, a simple approach like this can become limiting. Relay provides a number of features designed to help keep applications fast and reliable even as they grow in size and complexity: colocating data dependencies in components with GraphQL fragments, data consistency, mutations, etc. Check out Thinking in GraphQL and Thinking in Relay for an overview of how Relay makes it easier to work with GraphQL.

Step 4: Adding Relay To Our Project#

In this guide we'll demonstrate installing the experimental release of Relay Hooks, a new, hooks-based Relay API that supports React Concurrent Mode and Suspense.

First we'll add the necessary packages. Note that Relay is comprised of three key pieces: a compiler (which is used at build time), a core runtime (that is React agnostic), and a React integration layer.

4.1 Configure Relay Compiler#

Next let's configure Relay compiler. We'll need a copy of the schema as a file. If you're using the GitHub GraphQL API, you can download a copy directly from the Relay example app:

Note: On Windows, the file has to be explicitly saved with UTF-8 encoding, not the default UTF-16. See this issue for more details.

If you're using your own API we suggest using the utility to download your schema into a file.

Now that we have a schema we can modify to run the compiler first whenever we build or start our app:

At this point, you should be able to run the following successfully:

If it works, your app will open at localhost:3000. Now when we write GraphQL in our app, Relay will detect it and generate code to represent our queries in . We recommend checking in these generated files to source control.

4.2 Configure Relay Runtime#

Now that the compiler is configured we can set up the runtime - we have to tell Relay how to connect to our GraphQL server. We'll reuse the utility we built above. Assuming you haven't modified it (or at least that it still takes and as arguments), we can now define a Relay . An encapsulates how to talk to our server (a Relay ) with a cache of data retrieved from that server. We'll create a new file, and add the following:

Step 5: Fetching a Query With Relay#

Now that Relay is installed and configured we can change to use it instead. We'll prepare our data as the app starts, and wait for it to be ready in . Replace the contents of with the following:

Note that you'll have to restart the app - - so that Relay compiler can see the new query and generate code for it. See the Relay Compiler setup docs for how to run Relay Compiler in watch mode, to regenerate code as you modify queries.

Step 6: Explore!#

At this point we have an app configured to use Relay. We recommend checking out the following for information and ideas about where to go next:

  • The Guided Tour describes how to implement many common use-cases.
  • The API Reference has full details on the Relay Hooks APIs.
  • The Example App is a more sophisticated version of what we've started building here. It includes routing integration and uses React Concurrent Mode and Suspense for smooth transitions between pages.

Is this page useful?

Edit this page

Last updated on by Mofei Zhang

Deep dive on Relay GraphQL client for React

When we originally planned the app we discussed the choice of data layer and compared Redux (which was eventually used) with an alternative Facebook Open Source project called Relay.

At the time, Redux was chosen because it offered the simpler data implementation of the two, and was quicker and easier to integrate with our Parse data storage.

Once the app was released to the iOS and Android app stores, we wanted to revisit that choice, and look at how Relay could work with our app.

Gradual Evolution

With traditional native app development, the choice to switch the data layer would usually lead to a whole-scale rewrite of the entire app, where the existing functionality would be entirely swapped out.

React Native is very different - we can retain the majority of our existing data setup (Redux, Parse, and the relevant bindings) while also switching to a new data layer for an individual View. Instead of having to rebuild the app from scratch, or do a messy refactor, we can simply adjust one section of the app to use a new data layer and let the rest continue to use the existing layer.

It is worth stating just how huge a benefit this is to continued development of an app - the ability to progressively enhance an app reduces the overhead for maintenance and updates drastically.

So how does using Relay and GraphQL compare to the Redux model of thinking about data?

Introducing Relay and GraphQL

Firstly, and in very simple terms, Relay is the data framework that lives inside the app, and GraphQL is a query language used within Relay to represent the data schema. GraphQL is also run on a server separately from the app to provide a data source for Relay to interact with.

Relay isn't derived from the Flux architecture and is used only with GraphQL, which immediately means a big difference from the Redux model. The Store/Reducer/Component interaction we covered in the data tutorial does not really exist with Relay. It takes a different approach, and removes a lot of the building work you normally need to do when integrating data.

With Relay, each React component specifies exactly what data it depends on, using GraphQL. Relay handles everything about fetching that data, providing the component with updates when the data changes, and caching the data client-side. Anytime the app wants to change the data itself, it creates a GraphQL Mutation instead of an Action as with Redux.

An Example from the F8 App

Given the ability to progressively change a small part of a React Native app, we chose, as a kind of proof-of-concept, to swap Redux for Relay in the Demos View of the F8 app:

Demos view of F8 iOS app

This part of the app is pretty much entirely separate from the rest, with largely non-interactive content, making it an ideal place to start.

The view itself contains a simple function to render the demos list:

This is just a basic layout with some other simple info displaying components inside of it, but where are the parameters to the render method coming from? Well, inside the same .js file, we have a :

Here we're defining exactly what data the method needs to be displayed, as a GraphQL query. This corresponds to the GraphQL object that we are defining on our GraphQL server:

You can see how the data is fetched by the GraphQL server, then Relay takes care of grabbing all the required data specified in the fragment. This data becomes available as the parameters in the function passed to the 's' render prop.

Thanks to Relay's built-in logic, we don't need to worry about subscribing to data changes, or caching data in a Store, or anything else - we just tell Relay what data our component should have, and we design our component in the standard React way. With our GraphQL server already set up, that's all we need to do.

We have no data changes in this view, however if you want to learn more about how they work, please read the Relay docs on mutations.


Similar news:

Introducing Relay and GraphQL

Data fetching for React applications

There’s more to building an application than creating a user interface. Data fetching is still a tricky problem, especially as applications become more complicated. At React.js Conf we announced two projects we’ve created at Facebook to make data fetching simple for developers, even as a product grows to include dozens of contributors and the application becomes as complex as Facebook itself.

The two projects — Relay and GraphQL — have been in use in production at Facebook for some time, and we’re excited to be bringing them to the world as open source in the future. In the meantime, we wanted to share some additional information about the projects here.

What is Relay?

Relay is a new framework from Facebook that provides data-fetching functionality for React applications. It was announced at React.js Conf (January 2015).

Each component specifies its own data dependencies declaratively using a query language called GraphQL. The data is made available to the component via properties on .

Developers compose these React components naturally, and Relay takes care of composing the data queries into efficient batches, providing each component with exactly the data that it requested (and no more), updating those components when the data changes, and maintaining a client-side store (cache) of all data.

What is GraphQL?

GraphQL is a data querying language designed to describe the complex, nested data dependencies of modern applications. It’s been in production use in Facebook’s native apps for several years.

On the server, we configure the GraphQL system to map queries to underlying data-fetching code. This configuration layer allows GraphQL to work with arbitrary underlying storage mechanisms. Relay uses GraphQL as its query language, but it is not tied to a specific implementation of GraphQL.

The value proposition

Relay was born out of our experiences building large applications at Facebook. Our overarching goal is to enable developers to create correct, high-performance applications in a straightforward and obvious way. The design enables even large teams to make changes with a high degree of isolation and confidence. Fetching data is hard, dealing with ever-changing data is hard, and performance is hard. Relay aims to reduce these problems to simple ones, moving the tricky bits into the framework and freeing you to concentrate on building your application.

By co-locating the queries with the view code, the developer can reason about what a component is doing by looking at it in isolation; it’s not necessary to consider the context where the component was rendered in order to understand it. Components can be moved anywhere in a render hierarchy without having to apply a cascade of modifications to parent components or to the server code which prepares the data payload.

Co-location leads developers to fall into the “pit of success”, because they get exactly the data they asked for and the data they asked for is explicitly defined right next to where it is used. This means that performance becomes the default (it becomes much harder to accidentally over-fetch), and components are more robust (under-fetching is also less likely for the same reason, so components won’t try to render missing data and blow up at runtime).

Relay provides a predictable environment for developers by maintaining an invariant: a component won’t be rendered until all the data it requested is available. Additionally, queries are defined statically (ie. we can extract queries from a component tree before rendering) and the GraphQL schema provides an authoritative description of what queries are valid, so we can validate queries early and fail fast when the developer makes a mistake.

Only the fields of an object that a component explicitly asks for will be accessible to that component, even if other fields are known and cached in the store (because another component requested them). This makes it impossible for implicit data dependency bugs to exist latently in the system.

By handling all data-fetching via a single abstraction, we’re able to handle a bunch of things that would otherwise have to be dealt with repeatedly and pervasively across the application:

  • Performance: All queries flow through the framework code, where things that would otherwise be inefficient, repeated query patterns get automatically collapsed and batched into efficient, minimal queries. Likewise, the framework knows which data have been previously requested, or for which requests are currently “in flight”, so queries can be automatically de-duplicated and the minimal queries can be produced.
  • Subscriptions: All data flows into a single store, and all reads from the store are via the framework. This means the framework knows which components care about which data and which should be re-rendered when data changes; components never have to set up individual subscriptions.
  • Common patterns: We can make common patterns easy. Pagination is the example that Jing gave at the conference: if you have 10 records initially, getting the next page just means declaring you want 15 records in total, and the framework automatically constructs the minimal query to grab the delta between what you have and what you need, requests it, and re-renders your view when the data become available.
  • Simplified server implementation: Rather than having a proliferation of end-points (per action, per route), a single GraphQL endpoint can serve as a facade for any number of underlying resources.
  • Uniform mutations: There is one consistent pattern for performing mutations (writes), and it is conceptually baked into the data querying model itself. You can think of a mutation as a query with side-effects: you provide some parameters that describe the change to be made (eg. attaching a comment to a record) and a query that specifies the data you’ll need to update your view of the world after the mutation completes (eg. the comment count on the record), and the data flows through the system using the normal flow. We can do an immediate “optimistic” update on the client (ie. update the view under the assumption that the write will succeed), and finally commit it, retry it or roll it back in the event of an error when the server payload comes back.

How does it relate to Flux?

In some ways Relay is inspired by Flux, but the mental model is much simpler. Instead of multiple stores, there is one central store that caches all GraphQL data. Instead of explicit subscriptions, the framework itself can track which data each component requests, and which components should be updated whenever the data change. Instead of actions, modifications take the form of mutations.

At Facebook, we have apps built entirely using Flux, entirely using Relay, or with both. One pattern we see emerging is letting Relay manage the bulk of the data flow for an application, but using Flux stores on the side to handle a subset of application state.

Open source plans

We’re working very hard right now on getting both GraphQL (a spec, and a reference implementation) and Relay ready for public release (no specific dates yet, but we are super excited about getting these out there).

In the meantime, we’ll be providing more and more information in the form of blog posts (and in other channels). As we get closer to the open source release, you can expect more concrete details, syntax and API descriptions and more.

Watch this space!

Is this page useful?Edit this page


46 47 48 49 50