UNPKG

relay-runtime

Version:

A core runtime for building GraphQL-driven applications.

217 lines (165 loc) 6.49 kB
--- id: quick-start title: Quick Start slug: /getting-started/quick-start/ description: Get up and running with Relay keywords: - quick --- 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`](https://github.com/tobias-tengler/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](https://graphql.org/swapi-graphql/) hosted by graphql.org. ## Scaffold a React App We’ll start with a [Vite](https://vite.dev/) React app using TypeScript. ```bash npm create vite -- --template react-ts ``` You’ll be prompted for a project name. Type: `relay-example` ## Install Dependencies ```bash cd relay-example # Runtime dependencies npm install relay-runtime react-relay # Dev dependencies npm install --save-dev babel-plugin-relay graphql relay-compiler @rolldown/plugin-babel ``` :::tip If you're using an AI coding assistant, install the Relay best practices skill to make your agent a Relay expert: ```bash npx skills install facebook/relay ``` ::: ## Configure Vite to use Relay Relay uses a [Babel plugin](./babel-plugin.mdx) to insert code generated by the Relay compiler into your bundle. We can enable the Relay Babel plugin we installed earlier by configuring the Babel Vite plugin. ```tsx title="vite.config.ts" import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; // change-line import babel from "@rolldown/plugin-babel"; // https://vite.dev/config/ export default defineConfig({ // change-line plugins: [react(), babel({ plugins: ["relay"] })], }); ``` See [Babel Plugin](./babel-plugin.mdx) 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. ```bash 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](./compiler.mdx) which schema file we want it to use and other details about our project. ```json title="relay.config.json" { "src": "./src", "schema": "./schema.graphql", "language": "typescript" } ``` See [Relay Compiler](./compiler.mdx) 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. ```tsx title="src/main.tsx" import type { FetchFunction } from "relay-runtime"; 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 } 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](../api-reference/relay-runtime/relay-environment.mdx) for an overview of the Relay Environment and how to configure it. :::tip `<RelayEnvironmentProvider>` exposes your Environment via [React context](https://react.dev/learn/passing-data-deeply-with-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. ```tsx title="src/App.tsx" import type { AppQuery } from "./__generated__/AppQuery.graphql"; import { graphql, useLazyLoadQuery } from "react-relay"; import Film from "./Film.tsx"; 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](https://graphql.org/learn/queries/#fragments). ```typescript title="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](https://facebook.github.io/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. ::: ```bash npx relay-compiler npm run dev ``` You should now be able to open your app in a browser: [http://localhost:5173/](http://localhost:5173/) May the force be with you!