Quick Start
This quick start guide will start with a new React app using Vite and show you how to add Relay to it.
If you'd prefer an automated approach, create-relay-app
by Tobias Tengler will walk you through adding Relay to an existing React app via a series of prompts: npm create @tobiastengler/relay-app
We will be building a simple app which shows Star Wars movies fetched from the example Star Wars GraphQL API hosted by graphql.org.
Scaffold a React App​
We’ll start with a Vite React app using TypeScript.
npm create vite -- --template react-ts
You’ll be prompted for a project name. Type: relay-example
Install Dependencies​
cd relay-example
# Runtime dependencies
npm install relay-runtime react-relay
# Dev dependencies
npm install --dev babel-plugin-relay graphql relay-compiler
# Types
npm install --dev @types/relay-runtime @types/react-relay
Configure Vite to use Relay​
Relay uses a Babel plugin to insert code generated by the Relay compiler into your bundle. We can enable the Relay Babel plugin we installed earliery by configuring the React Vite plugin.
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [
react({ babel: { plugins: ["relay"] } })
],
})
See Babel Plugin for information about how to configure the Babel plugin for other build systems.
Configure the Relay Compiler​
Next we will download the GraphQL schema for the Star Wars GraphQL endpoint.
curl -O https://raw.githubusercontent.com/graphql/swapi-graphql/refs/heads/master/schema.graphql
And define our relay.config.json
config file which tells the Relay Compiler which schema file we want it to use and other details about our project.
{
"src": "./src",
"schema": "./schema.graphql",
"language": "typescript"
}
See Relay Compiler for more information about configuring and running the Relay compiler.
Configure your Relay Environment​
To allow components within our application to fetch GraphQL we configure a Relay Environment to fetch from our test endpoint and add it to React context.
import { StrictMode, Suspense } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";
import { RelayEnvironmentProvider } from "react-relay";
import { Environment, Network, FetchFunction } from "relay-runtime";
const HTTP_ENDPOINT = "https://graphql.org/graphql/";
const fetchGraphQL: FetchFunction = async (request, variables) => {
const resp = await fetch(HTTP_ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: request.text, variables }),
});
if (!resp.ok) {
throw new Error("Response failed.");
}
return await resp.json();
};
const environment = new Environment({
network: Network.create(fetchGraphQL),
});
createRoot(document.getElementById("root")!).render(
<StrictMode>
<RelayEnvironmentProvider environment={environment}>
<Suspense fallback="Loading...">
<App />
</Suspense>
</RelayEnvironmentProvider>
</StrictMode>
);
See Relay Environment for an overview of the Relay Environment and how to configure it.
<RelayEnvironmentProvider>
exposes your Environment via React context, so it must wrap your entire application.
Define your first Relay component​
Finally we can start defining the data we want to fetch and build our UI. Our app will fetch a list of films and render each one using a <Film>
component.
import { AppQuery } from "./__generated__/AppQuery.graphql";
import { graphql, useLazyLoadQuery } from "react-relay";
import Film from "./Film";
export default function App() {
const data = useLazyLoadQuery<AppQuery>(
graphql`
query AppQuery {
allFilms {
films {
id
...Film_item
}
}
}
`,
{}
);
const films = data?.allFilms?.films?.filter((film) => film != null);
return (
<div>
<h1>Star Wars Films</h1>
{films?.map((film) => (
<Film key={film.id} film={film} />
))}
</div>
);
}
Define your first fragment​
One of Relay's core principles is that each component should define its own data dependencies. So, we define our <Film>
component using a GraphQL Fragment.
import { graphql, useFragment } from "react-relay";
import type { Film_item$key } from "./__generated__/Film_item.graphql";
export default function FilmListItem(props: { film: Film_item$key; }) {
const film = useFragment<Film_item$key>(
graphql`
fragment Film_item on Film {
title
director
}
`,
props.film
);
return (
<li>
<b>{film.title}</b>: directed by <i>{film.director}</i>
</li>
);
}
Compile and run your app​
All that’s left is to run the Relay compiler and start your app!
The Relay compiler generates TypeScript types and combines your queries and fragments into optimized representations. You have to run the Relay compiler each time you modify your GraphQL queries or fragments.
If you have Watchman installed you can run npx relay-compiler --watch
to have the compiler run in watch mode, but you'll need to run echo "{}" > .watchmanconfig
to create a Watchman root.
npx relay-compiler
npm run dev
You should now be able to open your app in a browser: http://localhost:5173/
May the force be with you!