GraphQL and Relay

Getting Started with GraphQL and Relay

Abstract

This article is targeted towards the audience who want to do more than just handle UI on a networking application and want to handle data fetching and manipulation. Though there are many clients to handle data fetching, Apollo and Relay are amongst the most used and famous libraries when coupled with Graphql. Here, in this article, we’ll discuss the basic functionality and properties of Relay and it’s compatibility with Graphql. It is my suggestion that you should first have a basic understanding of GraphQL.

Introduction

Have you ever thought about the situation in which you want only limited things or data but you get a bunch of them and only a few are useful. For example Rest API, Its endpoint returns a fixed data structure, so the client usually always under or over fetched information.

This is where Graphql Comes to rescue as it gives clients the power to ask for exactly what they want and nothing more.

When building a react application, Relay couples React with the help of GraphQL and develop the idea of encapsulation. It allows components to specify what data they need and relay provide that data to the component. Relay is inspired by the flux in some manners. Instead of multiple stores, it has one central store that caches all store data.

GraphQL

GraphQL is a query language for your API, based on Graph algorithm. It provides an understandable description of the data in your API. It is developed by Facebook in 2012 and open-sourced in 2015. GraphQL allows developers to define types of Data. For Example:

query{

 allUsers {

name

contact

email

}}

And now the response you will get

{

“query”: {“allUsers”:[{

“First_Name”: “Anuj”

“Contact_No”: “*****”

“Email” : “xyz@abc.com

}]}

}

 It gives clients the power to ask for exactly what they want and nothing more, what you can see in the above example. GraphQL is not tied with any specific database or storage engine.

Since this article is towards the compatibility of Relay with GraphQL, I would not get into too many details that how GraphQL works on the server.

RelayRequest

Relay

Relay is a JavaScript framework which is used for building a data-driven react application. Data-driven, what it represents? For understanding purpose, data-driven is a model where you can control the flow of the program by offering different data set where the program logic is some generic form of flow or State changes.

Relay Supports:

  1. Declarative means you never need to again communicate with your data store using an imperative API. Simply declare what data you want using GraphQL and let Relay to figure out how and when your data to be fetched.
  2. Colocation, Data fetching queries is placed in the same location where the component view logic resides.
  3. Mutations, Relay helps you to mutate data on client and server using GraphQL mutation and it offers automatic data consistency, error handling, and optimistic updates.

    Now let set up the environment but before that, I will let you know that you should have basic knowledge of react, GraphQL, GraphQL server, and GraphQL Schema.

RelayReducers

Use GraphQL On The Client

Here are real discussion will start. For a very basic understanding, you can suppose GraphQL client is a code that sends the post request to GraphQL server. There are many ways by which you can use GraphQL on clients.

  1. Apollo Client 2.0
  2. Relay (newer version known as Relay Modern)
  3. FetchQL
  4. GraphQL Request
  5. Micro GraphQL React
  6. URQL
  7. React-Reach
  8. Lokka
  9. ApolloFetch
  10. Aws-Amplify

What are these clients, why we are using them? Is it not appropriate if we use plain HTTP to fetch data each time and iterate through all data until we get the right one?  Well, I hope you know better than me about this. If GraphQL provides you a way to abstract away a lot of manual work you’d usually have to do during that process and lets you focus on your real important work in your app.

Let’s consider some infrastructure feature that everyone probably wants in their app:

  1. Directly sending query and mutation without constructing HTTP request each time.
  2. Caching Data
  3. Validating and optimizing query process based on the schema.
  4. View layer Integration so when the response was received and handled by GraphQL client somehow needs to end up in your UI.

Apollo Client and Relay are two famous clients for GraphQL and we are going to discuss the compatibility of Relay with GraphQL.

Installation of Relay

Use yarn and npm for install React and Relay

yarn add react react-dom react-relay

or

npm add react react-dom react-relay

Modern Relay requires a babel plugin to convert GraphQL to runtime artifacts.

npm add –dev babel-plugin-relay graphql

or

yarn add –dev babel-plugin-relay graphql

add relay into list of plugins your .babelrc file

{

“plugins”: [“relay”]

}

*Note: Relay plugin should have run before another plugin to ensure that graphql template literals are completely transformed.

With some additional configurations, it can translate Relay Classic.  This plugin has some additional options like compact and schema, these options can be used for further customization for different environments. For Example:

{

  “plugins”: [

    [“relay”, {“compact”: true, “schema”: “path/schema.graphql”}]

  ]

}

You have also an alternative option, instead of using babel-plugin-relay, you can use Relay with babel-plugin-macros. After installing it add it into your babel config.

Const graphql =require (‘babel-plugin-relay/macro’);

Relay also require Relay compiler which you can install by executing below commands:

yarn add –dev relay-compiler

or

npm add –dev relay-compiler


This installs a bin script relay-compiler into your node module. After edit your application file just run the relay script to generate new compiled artifacts.

npm  run relay

or

yarn run relay

Or you have also an alternative where you can pass watch option which can look for changes into your file and automatically re-generate compiled artifacts. For that, you have to install watchman.

npm  run relay  –watch

or

yarn run relay  –watch

 Setup Relay Environment

Now what’s left for you is set up relay environment and write GraphQL query.

For environment setup, we have to bundle together configuration, network-handling and cache storage that relay needs in order to operate. Well, Relay environments need at least store and a network layer. The above code uses the default implementation of the store and creates a network layer using a simple fetch query.

import { Environment, GetRecordSource, Store,  Network } from ‘relay-runtime’;

function fetchRelatedQuery(operation, variables) { 

  return fetch(‘/graphql’, {

    method: ‘POST’,

    headers: {

      ‘Content-Type’: ‘application/json’,

    },

    body: JSON.stringify({

      query: operation.text,

      variables,

    }),

  }).then(response => {

    return response.json();

  });

}

 const environment = new Environment({

  network: Network.create(fetchRelatedQuery),

  store: new Store(new GetRecordSource()),  });

 export default environment;

 Now, we finished the relay environment setup so we can start fetching queries and rendering data on the screen.

Relay’s Methods and Properties

Here we will discuss some methods and properties provided by Relay.

1. Execute Query and Mutation

If you remember we discussed earlier GraphQL that how to write a query in GraphQL. Let’s start with how a query can be executed?

You have to pass query and variable into Query Renderer component provided by react-relay. You can pass a simple query or query with a variable. For Example:

import {graphql, commitMutation} from ‘react-relay’;

const mutation = graphql`

  mutation changeUserContact($input: userInput!) {

    changeUserData (input: $input) {

      user {

        id

        contact

      }

    }

  }

`;

function applyMutationForUser(environment, contact , user)

 {  return commitMutation(

    environment,

    { mutation,

      variables: {

        input: { contact, id: user.id},

      },

    }

  );

}

export default { applyMutationForUser };

 

We are using graphql for define query and pass environment, query, and variables to fetch data.  graphql is a template tag that is never executed at run time but used by relay compiler to generate the runtime artifacts that relay required to operate.

We can also mutate data using mutation tag. Like QueryRenderer for mutation, commit Mutation is used in Relay.

2. Methods

  • getMutation() (mutation that we want to use to specify a name of GraphQL)
  • getVariables() (to prepare data that can be sent as input arguments in the GraphQL mutation)
  • getFatQuery() (to specify all fields in our Relay Store that could have changed after the mutation)
  • getConfigs() (to tell Relay the way to deal with the response data)

3. Containers and Fragments

Containers are a higher-order component, it checks if the data is available and updates the component when the data has been updated.

Fragments, it allows composing component to queries. It is used by a container to define its own data requirement by creating a fragment list.

export default Relay.createContainer(

ListPage,

{

            fragments:{

                        viewer:( )=>Relay.QL`

                                                fragment on Viewer { id }

`,

},

},

)

4. Pagination Container

It is also a higher-order component, similar to a Fragment Container, which is designed to simplify the workflow of loading more items in a list in many cases, we don’t want to fetch all the data at once but want to lazily load more data. It depends on a GraphQL server exposing connections in a standardized way.

5. Relay Store

It is a class that has two static methods that are used to dispatching a mutation to the remote server, similar to calling an “Action” in Redux.

  • commitUpdate() (to dispatch mutation to the server)
  • applyUpdate() (similar to commitUpdate but it returns a transaction object to the mutation)

6. Types

Relay employs a client-side cache, which means whenever a mutation is sent to the server, Relay needs to know the way to update the cache with the mutation query result. Hence it is necessary to add mutation types for the getConfigs array.

Those types can be:

  • RANGE_ADD (create a new node)
  • FIELDS_CHANGE (update the existing nodes)
  • NODE_DELETE (delete a node)
  • RANGE_DELETE (delete edges between nodes)
  • REQUIRED_CHILDREN (It target fields that are not reachable, for example when a newly created node is desired to be redirected — rare cases)

7. Routes

Routes are normal objects that are used to declare root queries. The relay will combine the defined queries with fragments by using Relay. Renderer and send them to a remote server to fetch data.

8. Optimistic Response

The relay sends mutation to the server and update component after receiving a response. It updates the local state directly after receiving a response, but it is not optimistic approach. We can configure mutation to do an optimistic update. It means immediately updating our local data with what we expect it to be if we get a successful response from the server, updating the data immediately assuming that the mutation request will succeed. If it does not succeed, we can roll-back our update. For Example:

We just need to pass an optimistic response option, which refers to an object having the same shape as mutation response payload. When we pass this, Relay will know immediately to update local data with an optimistic response, and then update it with actual server response and roll it back if an error in the server response.

function getOptimisticResponseForUser(contact, user) {

  return {

    changeUserContact: {

      user: {

        contact,

        id: user.id,

      },

    },

  };

}

return commitMutation(

    environment,

    {

      mutation,

      variables: {

        input: {contact, id: user.id},

      },

      optimisticResponse: getOptimisticResponseForUser(contact, user),

    }

  );

 9. Relay Compiler and Directives

Relay uses Relay compiler to convert graphql literals into a generated file that remains alongside with your source file. It generates code as a part of build step which can be referenced at runtime, just because of this Relay’s runtime is not responsible for generating query strings and various optimization can be performed that could be expensive at runtime. If you need something unique you can build your own version of the compiler by swapping your own FileWriter and AstCache.

Relay uses a directive for adding additional information to graphql documents, which uses by Relay compiler to generate appropriate runtime artifacts. It only appears into your application code and removed when request sent to graphql server. @arguments, @ relay, @connection these are some directives.

Features of Relay Modern

  1. Smaller Bundle Size (20% of the size of React Classic).
  2. Garbage Collection, Remove cached data that is no longer referenced.
  3. GraphQL subscription and Live Query, using this imperative update API to modifications allow for the store whenever a payload is received.
  4. Simple Mutation API, Relay Modern introduced new mutation API that allows record and fields to be updated in a more direct manner.
  5. Injectable custom field handler, Relay Modern supports custom field handlers, can be used to process fields to work with various pagination patterns and other use cases.
  6. Client Schema Extension, It allows Relay to conveniently store extra information with data fetched from the server and to be rendered like other fields fetched from the server.
  7. Flow type generation from the Relay Compiler, It can help make an application less error-prone, by ensuring that all possible undefined cases are considered even if they don’t happen frequently.
  8. Performance, Relay Modern Core is lightweight and faster than previous versions, it is the result of removing a lot of complex features for dynamic queries. It means more memory is left for making UUI fells responsive. It also supports persisted queries and reducing the upload size of request from the full query text.
  9. Routes don’t need to know about a query root.
  10. Remove the restrictions from QueryRenderer and mutation query from Relay Classic.
  11. QueryRenderer supports for small data rendering directly without requiring a container.

Conclusion


Now I am going to conclude and I appreciate you that you have come so far to learn or understand Relay. After reading all the above content if you still think why we use Relay at all? If GraphQL does so much and works outside of Relay. Why do we need it? Well, the answer is GraphQL is not perfect on its own, it lacks the ability to poll and reactively update and some of its built-in inefficiencies make the system less optimum.

Relay, on the other hand, fixes many issues of it. Data caching, allow existing data to be reused instead of forcing new fetch to increase the efficiency. Part of this boost effectiveness comes from aggregation and colocation of queries into a single. Another huge benefit is its optimistic update, pagination, network traffic reduction, and pure volumetric reduction.

Optimistic updates, which is an interesting methodology for client mutations, allowing the user to interact with the changes they had done and simulated their experience without waiting for the server to complete the process.

Relay provides a system for Relay mutation updates, status reporting, and rollback, which allows more management of client and server states. Relay also supports rich pagination, reduce the heavy burden of large data returns and making them easier to consume and further improving the user experience.

Let’s wrap up, Overall point is that GraphQL needs Client, GraphQL cannot be perfect on its own. If you want to use GraphQL then you have many choices to pick one of the clients according to your requirement.

About Author:
Author Saurabh Singh is a Full-stack developer currently working with QSS Technosoft. He has completed his bachelor’s degree in Computer Science and Engineering. He is always ready to explore new technologies

About QSS:
QSS Technosoft is a top-notch ReactJS Development Company based in India & USA. The company offers the best React development services for building highly interactive cross-platform mobile apps at a lightning-fast speed.

Focusing on your success by creating most user-friendly web & mobile apps, the company feels proud mentioning its large base of happy clients from across the globe. Contact us for your React development requirements filling the form below.

Renovate unique Business Processes into Digitally Transformed solutions with QSS Technosoft!!

Do you want to remove manual operations, acting as impediment to your business growth? Realize your ideas into reliable web and mobile software solutions with our professional services. Take first step to launch your project by filling the form.

Let's computerize your business process


or Call Us