Skip to main content
Version: v19.0.0

Quick Start

This quick start guide will start with a new React app using Vite and show you how to add Relay to it.

tip

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.

vite.config.ts
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.

relay.config.json
{
"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.

src/main.tsx
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.

tip

<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.

src/App.tsx
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.

src/Film.tsx
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.

tip

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!