Configuring reactjs and relay 2019 version
The content here is under the Attribution 4.0 International (CC BY 4.0) license
Recently GraphQL started to gain attention from the open source community as a production ready platform focused on the communication between client and server. One of the advantages of GraphQL over REST is how the data is fetched from server to client, avoiding over fetching as well as under fetching.
Relay is an open source library that abstracts away the data fetching from the developer and offers a render component to the developer. Though, to configure relay and reactjs a few steps are needed. Even when following the official relay documentation to get up and running with React, problems can pop up.
The text follows with the reactjs set up using the create react app, then the relay configuration is presented guided by the relay official documentation and in conclusion the solution with the eject react app is presented.
- Disclaimer: To follow along NodeJs 10.* is a must as well as NPM 6.*.
- Disclaimer 2: The following of this text assumes that a graphql server up and running on localhost port 4002.
- Disclaimer 3: The text assumes general knowledge in handling terminal commands.
Related work
Despite previous attempts to setup reactjs and relay without ejecting the create react app [7][8], the approach to such options shows to not be effective as, the application created by create react by does not understand the configuration required for relay to work.
The relay.config.js
pointed by [7] demonstrates that the reactjs app
has difficulties to interpret the configuration file, leading to a broken
application state.
In the same sense [8] provides three different alternatives to setup relay and reactjs, which the third options elaborates more on how to use relay without ejecting. This approach as the previous one mentioned leads to a broken state application.
Setting up ReactJs
Create react app [1] is a opinionated tool that comes with webpack configuration and scripts abstracted away from the developer, providing good defaults. Creating an app react based with create react app takes two steps:
- Install create react app package (
npm i -g create-react-app
) - Executing the create react app (
create-react-app relay-app
)
Once the command from step 2 is done the react app is available in the relay-app
folder, make sure to move to that directory before proceeding with the
command cd relay-app
.
With the based app setup, the next step is to install all libraries required by relay to work.
npm i get-graphql-schema relay-compiler babel-plugin-relay --save-dev && npm i graphql react-relay --save
get-graphql-schema
[2] is a tool used for generating the graphql schema from a given
graphql server.
relay-compiler
[3] is used to convert graphql literals into generated
files that live alongside your source files. This approach facilitates the
usage of relay into reactjs project, preventing developers to write those files
themselves. babel-plugin-relay
is related as well, as it converts graphql to
runtime artifacts - without this plugin is not possible to run relay in the
browser.
At this stage a check point would help to make sure that the dependencies
have been installed and they are working as expected. For that, in the package.json
file add the following scripts [4]:
{
"scripts": {
"export-schema": "get-graphql-schema http://localhost:4002 > ./schema.graphql",
"relay-compile": "relay-compiler --src=./src --schema=./schema.graphql --artifactDirectory=./src/__generated__",
"relay": "npm run export-schema && npm run relay-compile"
}
}
The script export-schema
uses the library get-graphql-schema
to fetch
the schema definitions the the graphql server exposed at localhost:4002. The
schema.graphql
file is needed for the relay-compiler
package in order to
generate the query definitions.
relay-compile
generates the metadata used by relay to query the graphql server.
In this command the files and code generated are stored under src/__generated__
.
Finally, the relay
script is used as a shortcut to execute export-schema
and
relay-compile
in sequence.
Once the scripts have been added, the last step is to run the script relay
.
For that in the terminal run the following command:
npm run relay
The output should be something like the following:
> [email protected] relay /Projects/graph-ql/relay-app
> npm run export-schema && npm run relay-compile
> [email protected] export-schema /Projects/graph-ql/relay-app
> get-graphql-schema http://localhost:4002 > ./schema.graphql
`
> [email protected] relay-compile /Projects/graph-ql/relay-app
> relay-compiler --src=./src --schema=./schema.graphql --artifactDirectory=./src/__generated__
HINT: pass --watch to keep watching for changes.
Writing js
Unchanged: 0 files
The last line should reflect the project lack of graphql files, as in the last
line it shows Unchanged: 0 files
, which in this case is the desired
behavior.
Setting up relay environment
Relay requires an environment setup to work properly [5]. The environment
provided by the official documentation is the one used here. Copy the following
code and save it in a file called environment.js
.
import {
Environment,
Network,
RecordSource,
Store,
} from 'relay-runtime';
function fetchQuery(
operation,
variables,
) {
return fetch('/', {
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(fetchQuery),
store: new Store(new RecordSource()),
});
export default environment;
Next, comes the relay component to interact with the graphql server. The component
used here is a react functional component that creates a list of products
(file named ProductList.js
). The point of attention here is the environment
usage
defined previously, followed by the query
variable that holds the graphql query.
The graphql query is passed to the QueryRenderer
[6] relay component to fetch
the graphql data.
// ProductList.js
import React from 'react';
import {graphql, QueryRenderer} from 'react-relay';
import environment from './environment';
const query = graphql`
query ProductListQuery {
products {
title
image_link
}
}`;
const ProductListQuery = () =>
<QueryRenderer
environment={environment}
query={query}
render={RenderProductList}
/>;
const style = { color: 'red' };
export const RenderProductList = ({ error, props }) => {
if (error) {
return (<div style={style}>{error.message}</div>);
}
if (props) {
return props.products.map((item, index) =>
<div
key={index}
>
</div>
)
}
return <div>Loading</div>;
}
export default ProductListQuery;
The ProductList component is based on the component provided by the relay official
documentation [6]. To actually use the ProductList component one more step
is required: to invoke the component in the App.js
file, as the following code does.
import React from 'react';
import ProductList from './ProductList';
import './App.css';
function App() {
return (
<div className="App">
<ProductList />
</div>
);
}
export default App;
Once the code is in place, the expected behavior is to it to work, as the basic setup is completed. Unfortunately it doesn’t. Trying to run the code with the setup made so far throws an exception.
graphql: Unexpected invocation at runtime. Either the Babel transform was not set up, or it failed to identify this call site. Make sure it is being used verbatim as `graphql`.
The alternative solution proposed is to eject the reactjs app created with the create react app, the next section dives in details in how to achieve it.
The solution ejecting reactjs
The solution for that is to eject the reactjs project running the command:
npm run eject
. Followed by changing the babel configuration used.
The eject command reveals the magic behind the create react app, which results
in more configuration files in the root directory and more scripts/dependencies
in the package.json
file.
The next step is to create a new file named .babelrc
in the root of the project
and add the following content:
{
"presets": [
"react-app"
],
"plugins": [
[
"relay"
]
]
}
To prevent any babel configuration conflict, remove the section babel
inside
the package.json
file, and then, run again the command npm run relay
to
generate all required files by relay, this time time output should be something
like the following:
> [email protected] relay /Projects/relay-app
> npm run export-schema && npm run relay-compile
> [email protected] export-schema /Projects/relay-app
> get-graphql-schema http://localhost:4002 > ./schema.graphql
> [email protected] relay-compile /Projects/relay-app
> relay-compiler --src=./src --schema=./schema.graphql --artifactDirectory=./src/__generated__
HINT: pass --watch to keep watching for changes.
Writing js
Created:
- ProductListQuery.graphql.js
Unchanged: 0 files
Relay compiler is going to create one file, which is linked with the graphql query in the ProductList component.
At this point, starting the app with the command npm run start
should start the
reactjs app and relay should be up and running as well.
References
[1] Create React App - Set up a modern web app by running one command [Online]. Available: https://create-react-app.dev. [Accessed: 31 - Dec - 2019]
[2] Fetch and print the GraphQL schema from a GraphQL HTTP endpoint [Online]. Available: https://github.com/prisma-labs/get-graphql-schema. [Accessed: 31 - Dec - 2019]
[3] Set up relay-compiler [Online]. Available: https://relay.dev/docs/en/installation-and-setup#set-up-relay-compiler. [Accessed: 31 - Dec - 2019]
[4] How npm handles the “scripts” field [Online]. Available: https://docs.npmjs.com/misc/scripts. [Accessed: 31 - Dec - 2019]
[5] Relay environment [Online]. Available: https://relay.dev/docs/en/quick-start-guide#relay-environment. [Accessed: 31 - Dec - 2019]
[6] Rendering GraphQL Queries [Online]. Available: https://relay.dev/docs/en/quick-start-guide#rendering-graphql-queries. [Accessed: 31 - Dec - 2019]
[7] Set up Relay with a single config file [Online]. Available: https://relay.dev/docs/en/installation-and-setup#set-up-relay-with-a-single-config-file. [Accessed: 01 - Jan - 2020]
[8] Using Create React App with Relay Modern [Online]. Available: https://hackernoon.com/using-create-react-app-with-relay-modern-989c078fa892. [Accessed: 01 - Jan - 2020]
Table of contents
Got a question?
If you have question or feedback, don't think twice and click here to leave a comment. Just want to support me? Buy me a coffee!