React Native

Relay Setup

Introduction

In our previous guide, we’ve learned how to get the schema file, save it, and paste it on our React Native application. In this guide, we are going to install Relay and prepare our environment to start developing a React Native Application.

Goal

In order to set up Relay we will need first to install Relay on our React Native application and then prepare the Relay environment.

Prerequisites

  • We recommend a basic understanding of the following topics: Relay Modern, Babel JS, JavaScript (ECS5 and ECS6), GraphQL.js README*
  • A React Native basic project running on your local environment.
  • A schema.graphql file download on your React Native project.

In the following steps you’ll find a basic Relay installation focused on a React Native Application. If you want to deep dive into this topic please visit the official documentation.

Step 1 - Installing React Relay Official API

Let’s start installing the official library react-relay. This library is the Relay Core Team official API and has everything to build the data fragments.

1
yarn add [email protected]

Important installing Relay Modern for this tutorial with 10.0.0 as version. From verion 11.0.0 the approach to use the react-relay is different because of the new hooks.

Step 2 - Relay Config

The Relay Config has the info necessary for the Relay Compiler. Inside it, we will specify where Relay Compiler can find the schema.file, which folders should be looked up, and other configs. Let’s first install the relay-config package:

1
yarn add --dev relay-config

NOTE: This tutorial uses yarn as a package client, but you can use npm anyway.

Now let’s create the Relay Config file where Relay will find the schema path.

  • Create a new file inside the root of the application.
  • Name it as relay.config.js.

Open the file and save it with the information below:

1
2
3
4
module.exports = {
  schema: './data/schema.graphql',
  src: './',
};

Step 3 - Relay Babel Plugin

To convert the GraphQL artifacts at runtime, we need to install a babel plugin.

1
yarn add --dev babel-plugin-relay graphql

Now, inside your babel config file, you must add on plugins array the Relay Babel Plugin. The final babel.config.js will look like this:

1
2
3
4
5
{
  "plugins": [
    "relay"
  ]
}

In expo projects follow the same approach adding the plugins array inside of the babel.config.js right after the presets array. The final result should look:

1
2
3
4
5
6
7
8
9
10
11
module.exports = function (api) {
  api.cache(true);
  return {
    presets: [
      "babel-preset-expo",
    ],
    plugins: [
      'relay'
    ]
  };
};

The relay plugin must run before other plugins for a correct transformation of GraphQL artifacts. Check the plugin babel docs to know more.

Step 4 - Relay Compiler

Since our first documentation, we have been explaining about the Relay Compiler. For our application to compile our data fragments, we will install it now.

1
yarn add --dev relay-compiler

Let’s open our package.json and configure a new script command to run the relay compiler.

1
"relay": "relay-compiler --watchman false"

Watchman is responsible for configuring whether the Relay Compiler must be looking for any changes on relay fragments. If true it will rerun at each change. If false it will run after you run the yarn relay by itself.

The package.json file should look like this:

1
2
3
4
5
6
7
8
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint .",
    "relay": "relay-compiler --watchman false"
  },

Step 5 - Run yarn relay

Finally, with installation steps done, we can run the yarn relay command on the root of the application:

1
yarn relay

Since we don’t build any data fragment, the Relay Compiler returns any file changed:

Nice, your application has the Relay already installed and configured. Now, let’s implement our Environment to start making requests to the Back4App server.

Step 6 - Preparing the fetch environment

The Relay Environment defines how the Network Layer will handle the requests and how the Relay Store must work. The Store controls our data on the frontend by updating it only when changed and caching it. A simple Environment will need at least the Network Layer and the Store.

Network Layer

The Network Layer is easy to build. It will handle each request of our application, making queries, mutations, and subscriptions (if your application supports). Consuming it, the Relay will know-how to prepare the calls to access the application server.

Relay Store

The Store is responsible for update the data of our application on the client-side. Each request can have an updater function. Inside the updater function, you can use a list of helper functions to update your data with the Store Interface.

In order to prepare the Relay environment we need to create an environment config file. The file will be read by the Query Renderer every time a query is performed. Let’s prepare this file.

6.1 - Create the Environment File

We will follow the principle of design from Relay Library, the collocation concept. To start, let’s create a folder on the root of the application and name it relay. Inside it, create a file and name it environment.js.

6.2 - Configure the Environment

After that, import from relay-runtime all we need:

1
2
3
4
5
6
import {
    Environment,
    Network,
    RecordSource,
    Store,
} from 'relay-runtime';

6.3 - Configure the Network Layer

The network layer needs a function to fetch the data from the server. First of all, let’s create a fetch function responsible to perform a POST request:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const fetchQuery = async (request, variables) => {
  const body = JSON.stringify({
    query: request.text,
    variables,
  });

  const headers = {
    Accept: 'application/json',
    'Content-type': 'application/json',
    'X-Parse-Application-Id': 'X-Parse-Application-Id',
    'X-Parse-Client-Key': 'X-Parse-Client-Key',
  };

  try {
      const response = await fetch(`https://parseapi.back4app.com/graphql`, {
        method: 'POST',
        headers,
        body,
      });
  
      const data = await response.json();
  
      if (data.errors) {
        throw data.errors;
      }
  
      return data;
    } catch (err) {
      console.log('err on fetch graphql', err);
  
      throw err;
    }
};

We wrapper the request for the backend by a try-catch. Having an error will be thrown and the application will handle it. Otherwise will follow the normal behavior and return the data.

On Network Layer it’s also where you configure your application-server connection. At Back4App we use two main keys: Application Id and Client Key. The keys must be informed on the headers as long as the server URL. To get this information go to your App, and click on API Console -> GraphQL menu.

With the GraphQL console open, you will see the URL on the top, and on the bottom the application keys necessary. Replace with your info the fetch function.

Remember to do not expose the master key

6.4 - Export the Environment

The relay-runtime provides the functions necessary to consume the Network Layer and creates the Store. Finally, let’s combine them into a new Environment and export to our application. Use the code below on your Environment file.

1
2
3
4
5
6
const environment = new Environment({
  network: Network.create(fetchQuery),
  store: new Store(new RecordSource()),
});

export default environment;

Environment final file will look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import {
  Environment,
  Network,
  RecordSource,
  Store,
} from 'relay-runtime';

const fetchQuery = async (request, variables) => {
  const body = JSON.stringify({
    query: request.text,
    variables,
  });

  const headers = {
    Accept: 'application/json',
    'Content-type': 'application/json',
    'X-Parse-Application-Id': 'X-Parse-Application-Id',
    'X-Parse-Client-Key': 'X-Parse-Client-Key',
  };

  try {
        const response = await fetch(`https://parseapi.back4app.com/graphql`, {
          method: 'POST',
          headers,
          body,
        });
    
        const data = await response.json();
    
        if (data.errors) {
          throw data.errors;
        }
    
        return data;
      } catch (err) {
        console.log('err on fetch graphql', err);
    
        throw err;
      }
};

const environment = new Environment({
  network: Network.create(fetchQuery),
  store: new Store(new RecordSource()),
});

export default environment;

Conclusion

Awesome. Now with the Relay and Relay environment installed and configured it’s time to start to consume the Back4App GraphQL API. So, the next step is to create our first Query Renderer and communicate it to our server.