# Technical Documentation: facebook/relay

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/facebook/relay)

### Overview (README.md)

# [Relay](https://relay.dev) &middot; [](https://github.com/facebook/relay/blob/main/LICENSE) [](https://www.npmjs.com/package/react-relay)

Relay is a JavaScript framework for building data-driven React applications.

* **Declarative:** Never again communicate with your data store using an imperative API. Simply declare your data requirements using GraphQL and let Relay figure out how and when to fetch your data.
* **Colocation:** Queries live next to the views that rely on them, so you can easily reason about your app. Relay aggregates queries into efficient network requests to fetch only what you need.
* **Mutations:** Relay lets you mutate data on the client and server using GraphQL mutations, and offers automatic data consistency, optimistic updates, and error handling.

[See how to use Relay in your own project](https://relay.dev/docs/en/introduction-to-relay).

## Example

The [relay-examples](https://github.com/relayjs/relay-examples) repository contains an implementation of [TodoMVC](http://todomvc.com/). To try it out:

```
git clone https://github.com/relayjs/relay-examples.git
cd relay-examples/todo
yarn
yarn grats
yarn relay
yarn dev
```

Then, just point your browser at `http://localhost:5173`.

## Contribute

We actively welcome pull requests, learn how to [contribute](./.github/CONTRIBUTING.md).

## Users

We have a [community-maintained list](https://relay.dev/users/) of people and projects using Relay in production.

## License

Relay is [MIT licensed](./LICENSE).

## Thanks

We'd like to thank [the contributors](https://github.com/facebook/relay/graphs/contributors) that helped make Relay in open source possible.

The open source project [`relay-hooks`](https://github.com/relay-tools/relay-hooks) allowed the community to experiment with Relay and React Hooks, and was a source of valuable feedback for us. The idea for the `useSubscription` hook originated in [an issue](https://github.com/relay-tools/relay-hooks/issues/5#issuecomment-603930570) on that repo. Thank you [@morrys](https://github.com/morrys) for driving this project and for playing such an important role in our open source community.

Thank you for helping make this possible!

---

### Principles And Architecture Architecture Overview (`website/docs/principles-and-architecture/architecture-overview.mdx`)

---
id: architecture-overview
title: Architecture Overview
slug: /principles-and-architecture/architecture-overview/
description: Relay architecture overview guide
keywords:
- architecture
---

import DocsRating from '@site/src/core/DocsRating';

This document, together with [Runtime Architecture](../runtime-architecture/) and [Compiler Architecture](../compiler-architecture/), describes the high-level architecture of Relay. The intended audience includes developers interested in contributing to Relay, developers hoping to utilize the building blocks of Relay to create higher-level APIs, and anyone interested in understanding more about Relay internals. For developers wanting to learn more about _using_ Relay to build products, the [Tutorial](../tutorial/intro.mdx) is the best resource.

## Core Modules

Relay is composed of three core parts:

-   **Relay Compiler:** A GraphQL to GraphQL optimizing _compiler_, providing general utilities for transforming and optimizing queries as well as generating build artifacts. A novel feature of the compiler is that it facilitates experimentation with new GraphQL features - in the form of custom directives - by making it easy to translate code using these directives into standard, spec-compliant GraphQL.
-   **Relay Runtime:** A full-featured, high-performance GraphQL _runtime_ that can be used to build higher-level client APIs. The runtime features a normalized object cache, optimized "write" and "read" operations, a generic abstraction for incrementally fetching field data (such as for pagination), garbage collection for removing unreferenced cache entries, optimistic mutations with arbitrary logic, support for building subscriptions and live queries, and more.
-   **React/Relay:** A high-level _product API_ that integrates the Relay Runtime with React. This is the primary public interface to Relay for most product developers, featuring APIs to fetch the data for a query or define data dependencies for reusable components (e.g. `useFragment`).

Note that these modules are _loosely coupled_. For example, the compiler emits representations of queries in a well-defined format that the runtime consumes, such that the compiler implementation can be swapped out if desired. React/Relay relies only on the well-documented public interface of the runtime, such that the actual implementation can be swapped out. We hope that this loose coupling will allow the community to explore new use-cases such as the development of specialized product APIs using the Relay runtime or integrations of the runtime with view libraries other than React.

<DocsRating />

---

### Tutorial Intro (`website/docs/tutorial/intro.mdx`)

# Tutorial Intro

This tutorial will get you started with the most important and frequently-used features of Relay. To do that, we’ll build a simple app that displays a newsfeed. We will cover:

* How to fetch data using [Queries](./queries-1.mdx).
* How to make components self-contained by breaking [Queries](./queries-1.mdx) into [Fragments](./fragments-1.mdx).

This tutorial assumes a fair familiarity with React. If you’re still new to React, we suggest going through the [React tutorial](https://reactjs.org/tutorial/) and working with React until you’re comfortable with creating components, passing props, and using the basic hooks such as `useState`. The tutorial is based on the Web, but Relay also works great with React Native.

This tutorial is built with TypeScript, so [very basic knowledge of TypeScript](https://www.typescriptlang.org/docs/) is helpful as well — you don’t need to know anything beyond declaring and importing types and annotating functions. Relay can also be used with the Flow type system or without a type system.

:::info
**IMPORTANT**: The tutorial is meant to be gone through in order, as the exercises build on each other. You’ll be making incremental changes to an example app, so later section won’t make sense if you haven’t done the earlier sections.
:::

## Setup

To get started, run the following commands:

```
git clone https://github.com/relayjs/relay-examples.git
cd relay-examples/newsfeed
npm install
npm run dev
```

This downloads a template project to get started from and starts the server. (If they don’t work, you may need to [install git](https://github.com/git-guides/install-git) or [install npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).)

When you run `npm run dev`, several processes are started:

* A Webpack-based HTTP server that serves up the front-end code.
* A basic GraphQL server that the front-end will query to retrieve information.
* The Relay compiler, which processes the GraphQL in your app and generates additional files that Relay uses at runtime, as well as TypeScript types representing the inputs and results of your queries. It will automatically regenerate when you save changes in your files.

In the terminal output, these three processes’ log output are marked with tags: `[webpack]` in yellow, `[server]` in green, and `[relay]` in blue. Keep a look out for errors marked with `[relay]` as these are helpful if your GraphQL has any mistakes.

If you encounter errors in the `[relay]` process indicating: ```[relay] thread 'main' panicked at 'Cannot run relay in watch mode if `watchman` is not available (or explicitly disabled).'```, this means watchman is not installed or available on your system. To resolve this, you may need to [install watchman separately](https://facebook.github.io/watchman/docs/install). After installing watchman, try running `npm run dev` again.

Now that these processes are running, you should be able to open [http://localhost:3000](http://localhost:3000/) in your browser.



We start from a webpage that shows a single Newsfeed story rendered with React, but the data for that story is just placeholder data hard-coded into the React components. In the rest of this tutorial, we’ll make the app functional by having it fetch data from the server, paginate over multiple stories, and update the data by commenting and liking.

## Folder Structure

The files that make up the example app are laid out in this way:

* `src/components` — the front-end app components that we’ll be modifying and working with. Some of the important components are:
    * `App.tsx` — the top-level component
    * `Newsfeed.tsx` — a component that will run a query to fetch newsfeed stories and display a scrolling list of stories
    * `Story.tsx` — a component that shows a single newsfeed story.
* `server` — a very basic GraphQL server that serves up example data
    * `server/schema.graphql` — the GraphQL schema: it specifies what information can be queried from the server via GraphQL.

Finally, you may want to install the [Relay VSCode extension](https://marketplace.visualstudio.com/items?itemName=meta.relay) for autocomplete, errors, and other help when using VSCode.

Head over to the next section to start learning about GraphQL and Relay.

---

### Editor Support (`website/docs/editor-support.mdx`)

---
id: editor-support
title: Editor Support
slug: /editor-support/
keywords:
- LSP
- Language Server Protocol
- VS Code
- VSCode
---

import useBaseUrl from '@docusaurus/useBaseUrl';

*TL;DR: We have a [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=meta.relay)*

---

The Relay compiler has a rich understanding of the GraphQL embedded in your code. We want to use that understanding to improve the developer experience of writing apps with Relay. So, starting in [v14.0.0](https://github.com/facebook/relay/releases/tag/v14.0.0), the new Rust Relay compiler can provide language features directly in your code editor. This means:

#### Relay compiler errors surface as red squiggles directly in your editor

<img src={useBaseUrl('img/docs/editor-support/diagnostics.png')} />

#### Autocomplete throughout your GraphQL tagged template literals

<img src={useBaseUrl('img/docs/editor-support/autocomplete.png')} />

#### Hover to see type information and documentation about Relay-specific features

<img src={useBaseUrl('img/docs/editor-support/hover.png')} />

#### `@deprecated` fields are rendered using ~~strikethrough~~

<img src={useBaseUrl('img/docs/editor-support/deprecated.png')} />

#### Click-to-definition for fragments, fields and types

<img src={useBaseUrl('img/docs/editor-support/go-to-def.gif')} />

#### Quick fix suggestions for common errors

<img src={useBaseUrl('img/docs/editor-support/code-actions.png')} />

## Language Server

The editor support is implemented using the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) which means it can be used by a variety of editors, but in tandem with this release, [Terence Bezman](https://twitter.com/b_ez_man) from [Coinbase](https://www.coinbase.com/) has contributed an official VS Code extension.

[**Find it here!**](https://marketplace.visualstudio.com/items?itemName=meta.relay)

## Why Have a Relay-Specific Editor Extension?

The GraphQL foundation has an official language server and [VS Code extension](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql) which provides editor support for GraphQL generically. This can provide a good baseline experience, but for Relay users, getting this information directly from the Relay compiler offers a number of benefits:

* Relay compiler errors can surface directly in the editor as “problems”, often with suggested quick fixes
* Hover information is aware of Relay-specific features and directives and can link out to relevant documentation

---

### Home (`website/docs/home.mdx`)

---
id: home
title: Home
slug: /
description: Relay documentation landing page
keywords:
- relay
- graphql
- data
- introduction
- home
---

# Relay Docs

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

Relay is a powerful [GraphQL](https://graphql.org/) client for [React](https://react.dev/). It embodies years of learning to give you **outstanding performance by default** while keeping your code **scalable and maintainable**.

Relay brings the composability of React components to data fetching. Each component declares its own data needs, and Relay combines them into efficient pre-loadable queries. Every aspect of its design is to make the natural way of writing components also the most performant.

## Features

* **Declarative**: Just declare what data each component needs and Relay will handle generating [optimal queries](https://relay.dev/blog/2023/10/24/how-relay-enables-optimal-data-fetching/) for each surface.
* **Composable**: Components act like building bricks that can click into place anywhere in your app without needing to manually update queries.
* **Pre-fetchable**: Relay's generated queries allow you to start fetching data for your surface before your code even downloads or runs.
* **Built-in UI patterns**: Relay implements loading states, pagination, refetching, optimistic updates, rollbacks, and other common UI behaviors that are tricky to get right.
* **Consistent state**: Relay maintains a normalized data store, so components that observe the same data stay in sync even if they reach it by different queries.
* **Type safe**: Relay generates TypeScript types for each GraphQL snippet so that errors are caught statically, not at runtime.
* **Streaming/deferred data**: Declaratively defer parts of your query and Relay will progressively re-render your UI as the data streams in.
* **Developer experience**: Relay's [editor support](./editor-support.mdx) provides autocompletion and go-to-definition for your GraphQL schema.

---

### Community Learning Resources (`website/docs/community/learning-resources.mdx`)

---
id: learning-resources
title: Community Learning Resources
slug: /community-learning-resources/
---

import useBaseUrl from '@docusaurus/useBaseUrl';
import DocsRating from '@site/src/core/DocsRating';
import {FbInternalOnly, OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## Guides and articles:

-   [How to use @argumentsDefinitions to define local variables to your fragments](https://medium.com/entria/relay-modern-argumentdefinitions-d53769dbb95d) (by Entria)
-   [Deep Dive of Updater Relay Store function. How to update your store properly after a mutation or subscription](https://medium.com/entria/wrangling-the-client-store-with-the-relay-modern-updater-function-5c32149a71ac) (by Entria)
-   [Optimistic Update: how to update your UI before server responds](https://medium.com/entria/relay-modern-optimistic-update-a09ba22d83c9) (by Entria)
-   [Relay Network Deep Dive - how to incrementally improve your network layer to manage complex data fetching requirements](https://medium.com/entria/relay-modern-network-deep-dive-ec187629dfd3) (by Entria)
-   [Relay Modern with TypeScript - how to configure Relay Modern to make it with TypeScript](https://medium.com/@sibelius/relay-modern-migration-to-typescript-c26ab0ee749c) (by @sibelius)
-   [Collection of random thoughts and discoveries around Relay](https://mrtnzlml.com/docs/relay)

<OssOnly>

## Relay example projects

These projects serve as an example of how to use Relay in real world applications. Some of them are even with educational videos.

-   [github.com/relayjs/relay-examples](https://github.com/relayjs/relay-examples)
-   [github.com/adeira/relay-example](https://github.com/adeira/relay-example)
-   [github.com/juffalow/react-relay-example](https://github.com/juffalow/react-relay-example)

## Learn basics

Here, you will find articles written by the Relay community. They touch on basic topics that are necessary for daily work.

-   [What is a fragment? Basic explanation of what is a fragment and what it is used for](https://medium.com/@sibelius/relay-modern-what-is-a-fragment-c70f164c2469) (by @sibelius)
-   [Relay anti-patterns. What you should avoid doing when using Relay concepts](https://medium.com/entria/relay-apollo-anti-pattern-d9f4dea47738) (by Entria)
-   [Insights of how Relay Modern has improved a lot since Relay Classic](https://medium.com/entria/relay-is-just-getting-better-54112ffc1a9e) (by Entria)
-   [How to use @argumentsDefinitions to define local variables to your fragments](https://medium.com/entria/relay-modern-argumentdefinitions-d53769dbb95d) (by Entria)
-   [How to paginate using a Refetch Container. You can use a refetch container to paginate as well, just use renderVariables correctly](https://medium.com/entria/relay-modern-pagination-using-refetch-container-editing-a07c6b33ae4e) (by Entria)

## About Relay Store

-   [How Relay Modern stores your data](https://medium.com/@sibelius/relay-modern-the-relay-store-8984cd148798) (by @sibelius)
-   [Deep Dive of Updater Relay Store function. How to update your store properly after a mutation or subscription](https://medium.com/entria/wrangling-the-client-store-with-the-relay-modern-updater-function-5c32149a71ac) (by Entria)
-   [Optimistic Update: how to update your UI before server responds](https://medium.com/entria/relay-modern-optimistic-update-a09ba22d83c9) (by Entria)
-   [Local State Management, part 1 - how to create a controlled input using Relay](https://babangsund.com/relay_local_state_management/) (by @babangsund)
-   [Local State Management, part 2 - how to manage global state and localStorage persistence on the client, using Relay](https://babangsund.com/relay_local_state_management_2/) (by @babangsund)
-   [Local State Management, part 3 - using LocalQueryRenderer and local state to manage nested fragments](https://babangsund.com/relay_local_state_management_3/) (by @babangsund)

## Network Layer

-   [Relay Network Deep Dive - how to incrementally improve your network layer to manage complex data fetching requirements](https://medium.com/entria/relay-modern-network-deep-dive-ec187629dfd3) (by Entria)

## Relay Configuration

-   [Relay Modern with TypeScript - how to configure Relay Modern to make it with TypeScript](https://medium.com/@sibelius/relay-modern-migration-to-typescript-c26ab0ee749c) (by @sibelius)

## Miscellaneous

-   [Relay Modern Learning Blog Posts Thread on Twitter](https://twitter.com/sseraphini/status/1078595758801203202)
-   [Collection of random thoughts and discoveries around Relay](https://mrtnzlml.com/docs/relay)

</OssOnly>

<DocsRating />

---

### Debugging Declarative Mutation Directives (`website/docs/debugging/declarative-mutation-directives.mdx`)

---
id: declarative-mutation-directives
title: Debugging Declarative Mutation Directives
slug: /debugging/declarative-mutation-directives/
description: Debugging declarative mutation directives
keywords:
- debugging
- troubleshooting
- declarative mutation directive
- deleteRecord
- handlerProvider
- appendEdge
- prependEdge
- appendNode
- prependNode
---

// @fb-only

If you see an error similar to:

```
RelayFBHandlerProvider: No handler defined for `deleteRecord`. [Caught in: An uncaught error was thrown inside `RelayObservable`.]
```

or

```
RelayModernEnvironment: Expected a handler to be provided for handle `deleteRecord`.
```

This probably means that you are using a Relay environment to which a `handlerProvider` is passed. However, the handler provider does not know how to accept the handles `"deleteRecord"`, `"appendEdge"` or `"prependEdge"`. If this is the case, you should return `MutationHandlers.DeleteRecordHandler`, `MutationHandlers.AppendEdgeHandler`, or `MutationHandlers.PrependEdgeHandler` respectively (these can be imported from `relay-runtime`).

// @fb-only

---

### Debugging Disallowed Id Types Error (`website/docs/debugging/disallowed-id-types-error.mdx`)

---
id: disallowed-id-types-error
title: Disallowed Types for `id` Fields
slug: /debugging/disallowed-id-types-error
description: Disallowed types for `id` fields
keywords:
- debugging
- troubleshooting
- disallowed
- id
- Object Identification
---

import DocsRating from '@site/src/core/DocsRating';

If you see an error from the compiler that reads something like:

```
Disallowed type `String` of field `id` on parent type `Foo` cannot be used by Relay to identify entities
```

This means that your GraphQL schema defines an object with a field named `id` that doesn't have a valid type. Valid types for this field are `ID` or `ID!` unless configured otherwise. While there may be a valid reason in your application to have that field defined that way, the Relay compiler and runtime will mishandle that field and cause refresh or data updating issues.

## Disallowing `id` fields without type `ID`

Recall that Relay uses [Object Identification](../../guides/graphql-server-specification/#object-identification) to know which GraphQL objects to refetch. In the usual case, those GraphQL objects implement the [`Node` interface](https://graphql.org/learn/global-object-identification/#node-interface) and thus come with an `id` field with type `ID`. However, there are types in your GraphQL model that may not require unique identification. For that reason, Relay (by default) does not restrict object definitions, allowing `id` fields with non-`ID` types (e.g. `String`) to be defined.

This poses a bit of difficulty to both Relay's compiler and runtime. In short, the runtime and compiler only properly handle `id` fields as defined by the `Node` interface. Any selections made with non-`Node` `id` fields will likely exhibit undesirable and unintended Relay behavior on your components (e.g. components not re-rendering on re-fetched data).

### The significance of the `ID` type

[Global Object Identification in GraphQL](https://graphql.org/learn/global-object-identification/)) is what underlies Relay's Object Identification. The `id` field supplied by the `Node` interface is specified to be a unique identifier that can be used for storage or caching.

## Fix: Define your `id` fields as `ID`

To ensure Relay correctly manages objects fetched to your application, here are two recommended courses of action:

* Ensure all fields named `id` are typed with `ID`
* Rename any fields named `id` (with a type that isn't `ID`) to a different name (e.g. `special_purpose_id`)

If your application truly requires that `id` field's definition to remain as-is and you are aware of the problems that may arise, you can add your GraphQL type and the type of its `id` field to the allowlist in `nonNodeIdFields` of the [Relay Compiler's Configuration](https://github.com/facebook/relay/tree/main/packages/relay-compiler). Note that this will only bypass the error for that combination of object type and `id` field type.

<DocsRating />

---

### Debugging Inconsistent Typename Error (`website/docs/debugging/inconsistent-typename-error.mdx`)

---
id: inconsistent-typename-error
title: Inconsistent Typename Error
slug: /debugging/inconsistent-typename-error/
description: Debugging inconsistent typename errors in Relay
keywords:
- debugging
- troubleshooting
- inconsistent typename
- RelayResponseNormalizer
- globally unique id
---

import DocsRating from '@site/src/core/DocsRating';
import {FbInternalOnly, OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## Inconsistent `__typename` error

The GraphQL server likely violated the globally unique ID requirement by returning the same ID for different objects.

If you're seeing an error like:

```
`RelayResponseNormalizer: Invalid record '543'. Expected __typename to be consistent, but the record was assigned conflicting types Foo and Bar. The GraphQL server likely violated the globally unique ID requirement by returning the same ID for different objects.`
```

the server implementation of one of the types is not spec compliant. We require the `id` field to be globally unique. This is a problem because Relay stores objects in a normalized key-value store and one of the object just overwrote the other. This means your app is broken in some subtle or less subtle way.

## Common cause

The most common reason for this error is that 2 objects backed by an ID are using the plain ID as the id field, such as a `User` and `MessagingParticipant`.

Less common reasons could be using array indices or auto-increment IDs from some database that might not be unique to this type.

## Fix: Make your type spec compliant

The best way to fix this is to make your type spec compliant. For the case of 2 different types backed by the same ID, a common solution is to prefix the ID of the less widely used type with a unique string and then base64 encode the result. This can be accomplished fairly easily by implementing a `NodeTokenResolver` using the helper trait `NodeTokenResolverWithPrefix`.  When the `NodeTokenResolver` is registered it allows you to load your type using `node(id: $yourID)` GraphQL call and your type can return an encoded ID.

<FbInternalOnly>

### Example

See [D17996531](https://www.internalfb.com/diff/D17996531) for an example on how to fix this. It created a `FusionPlatformComponentsCategoryNodeResolver` added the trait `TGraphQLNodeMixin` to the conflicting class so that it generates the base64 encoded ID.

</FbInternalOnly>

<DocsRating />

---

### Debugging Relay Devtools (`website/docs/debugging/relay-devtools.mdx`)

---
id: relay-devtools
title: Relay DevTools
slug: /debugging/relay-devtools/
description: Debugging guide for the Relay DevTools
keywords:
- debugging
- troubleshooting
- extension
- devtools
- browser
---

import DocsRating from '@site/src/core/DocsRating';
import {FbInternalOnly, OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## Installation

<FbInternalOnly>

### Internal version (preferred)

The internal version of devtools has the latest updates and the process of installation will be much faster.

1. Before downloading the new Devtools, make sure you've deleted all older versions of the extension.
2. Join [Relay Support](https://fb.workplace.com/groups/relay.support) group and you will automatically be added to the `cpe_relay_devtools_extension` gatekeeper.
3. Wait 20-30 minutes, and it should be downloaded on your Chrome browser
4. Or run `sudo soloctl -i` on your machine to get the extension immediately

### Internal Version for Edgium users

1. On `C:\Users\<User>\AppData\Local\Google\Chrome\User Data\<Work Profile>\Extensions` search for files manifest.json with Relay Developer Tools on it
2. Get the path to this folder e.g `...\Extensions\<blob>\<version>\`
3. On edge://extensions/ click load upacked (you might need to Allow extensions for other stores).

### External version (use at your own risk)

The external version of Dev Tools does not always contain the latest updates, it may stop working, potentially being restricted to be used or removed by corp device admin (via MDM).
We recommend using the internal installation, but if you prefer, you may download the extension from the [Chrome store](https://chrome.google.com/webstore/detail/relay-developer-tools/ncedobpgnmkhcmnnkcimnobpfepidadl).

</FbInternalOnly>

<OssOnly>

Follow this link and install it from the [chrome store](https://chrome.google.com/webstore/detail/relay-developer-tools/ncedobpgnmkhcmnnkcimnobpfepidadl).

</OssOnly>

---

## How to Navigate the Relay DevTools Extension

You should have a new tab called Relay in your Chrome DevTools. In this tab, you will be able to select between 2 panels: the **network panel** and the **store panel**.

### Network Panel

The network panel allows users to view individual requests in an active environment. Users can scroll through these requests, search for the requests and view the details of each request. The details of each request includes the status, the variables, and the responses for the request.

###  Store Panel

The store panel allows users to view individual records from the store data in an active environment. Users can scroll through these records, search for the records, and view the details of each request. Users can also copy the store data in JSON format to the clipboard. The details of each record includes the ID, the typename, and all of the data in the record. If one of the fields in the data is a reference to another record, users can click on the reference, which will take them to that record.

---

## Multiple Environments

As you switch through the store and network panels, you'll notice that there is also a dropdown menu on the left side of the developer tools. This dropdown allows users to switch between environments. The requests in the network tab and the store data are grouped by environment, so users can easily shuffle between active environments.

## Give Feedback

Look in the top-right corner of the extension panel!

<DocsRating />

---

### Debugging Why Null (`website/docs/debugging/why-null.mdx`)

---
id: why-null
title: "Why Is My Field Null?"
slug: /debugging/why-null/
description: Get help figuring out why a given field is unexpectedly null.
keywords:
- "null"
- missing
- optional
- nullthrows
---

import {FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
import DocsRating from '@site/src/core/DocsRating';

There are a number of reasons that a field read by Relay can be null and some of them are obscure or unintuitive. When debugging an unexpectedly null value, it can be helpful to understand both the common cases and edge cases that can cause a field to be read as null. This document enumerates the cases that can lead to null or missing values with tips for determining which case you are in.

## Server Returned Null

The simplest reason a field might be null is that the server explicitly returned null. This can happen in two cases:

1. The server’s field resolver returned an explicit null
2. The field resolver throws. In this case GraphQL will return null for that field. *This is true even if the server resolver’s return type is non-nullable.* The one exception is fields annotated as non-null. In that case server should *never* return null. If an exception is encountered the entire parent object will be nulled out.

<FbInternalOnly>

:::note
At Meta, non-nullable fields are implemented using [`KillsParentOnException`](https://www.internalfb.com/intern/wiki/Graphql-for-hack-developers/fields/return-type/#non-nullable-fields).
:::

</FbInternalOnly>

**🕵️‍♀️ How to tell:** Inspect the server’s response using Relay Dev tools, or in your browser’s dev tools’s network tab, to see if the field is null.

## Graph Relationship Change

If a different query/mutation/subscription observes a relationship change in the graph, you may end up trying to read fields off of an object which your query never fetched.

Imagine you have a query that reads your best friend’s name:

```graphql
query MyQuery {
  me {
    best_friend {
      # id: 1
      name
    }
  }
}
```

After you get your query response, *who* your best friend is *changes* on the server. Then a *different* query/mutation/subscription fetches a different set of fields off of `best_friend`.

```graphql
query OtherQuery {
  me {
    best_friend {
      # new id: 2
      # Note: name is not fetched here
      age
    }
  }
}
```

Because the Relay store is normalized, we will update the `me` record to indicate that `best_friend` linked field now points to the user with ID 2, and the only information we know about that user is their age.

This will trigger a rerender of `MyQuery`. However, when we try to read the `name` field off of the user with ID 2, we won’t find it, since the only thing we know about the user with ID 2 is their `age`. Note that a relationship “change” in this case, could also mean a relationship that is new. For example, if you start with no best friend but a subsequent response returns *some* best friend, but does not fetch all fields your component needs.

**Note**: In theory, Relay *could* refetch your query when this state is encountered, but some queries are not safe to re-issue arbitrarily, and more generally, UI state changing in a way that’s not tied to a direct user action can lead to confusion. For this reason, we have chosen not to perform refetches in this scenario.

**🕵️‍♀️ How to tell:** You can place a breakpoint/`console.log` at the finale return statement of `readWithIdentifier` in `FragmentResource` ([code pointer](https://github.com/facebook/relay/blob/2b9876fcbf0845cd23728d4d720712525ff424c4/packages/react-relay/relay-hooks/FragmentResource.js#L475). This is the point in Relay at which we know that we are missing data, but there is not query in flight to get it.

## Inconsistent Server Response

This is a **rare edge case**, *but* if the server does not correctly implement the [field stability](https://graphql.org/learn/global-object-identification/#field-stability) semantics of the id field, it’s possible that a field could be present in one part of the response, but *explicitly null* in another.

```graphql
{
  me {
    id: 1
    name: "Alice"
  }
  me_elsewhere_in_the_graph {
    id: 1 # Note this is the same as the `me` field above...
    name: null
  }
}
```

In this case, Relay first learns that user 1’s `name` is Alice, but later in the query finds that user 1’s `name` has now `null`. Because Relay stores data in a normalized store, user 1 can only have one value for `name` and Relay will end in a state where user 1’s `name` is `null`.

**🕵️‍♀️ How to tell:** Relay is smart enough to detect when this has happened, and will [log an error to the console](https://github.com/facebook/relay/blob/2b9876fcbf0845cd23728d4d720712525ff424c4/packages/relay-runtime/store/RelayResponseNormalizer.js#L505) in dev that looks like: “RelayResponseNormalizer: Invalid record. The record contains two instances of the same id: 1 with conflicting field, name and its values: Alice and null.". Additionally, you can manually inspect the query response.

Note that if the unstable field is a linked field (edge to another object), this type of bug can cause a Graph Relationship Change (described above) to occur *within a single response*. For example, if a user with the same `id` appears in two places in the response, but their `best_friend` is different in those two locations.

**🕵️‍♀️ How to tell:** Relay is also smart enough to detect this case, and will show a [similar console warning](https://github.com/facebook/relay/blob/2b9876fcbf0845cd23728d4d720712525ff424c4/packages/relay-runtime/store/RelayResponseNormalizer.js#L844) in dev.

<FbInternalOnly>

:::note
Because these errors exist in the codebase and can cause noisy console output, these warnings are [disabled](https://www.internalfb.com/code/www/[5b26a6bd37e8]/html/shared/core/WarningFilter.js?lines=559) in dev mode.
:::

</FbInternalOnly>


## Client-side Deletion or Incomplete Update

Imperative store updates, or optimistic updates could have deleted the record or field. If an imperative store update, or optimistic update, writes a new record to the store, it may not supply a value for a field which you expected to be able to read. This is a fundamental problem, since an updater cannot statically know all the data that might be accessed off of a new object.

**🕵️‍♀️ How to tell:** Due to React and Relay’s batching, it’s not always possible to associate a component update with the store update that triggered it. Here, your best bet is to set a breakpoint in your component for when your value is null, and then use the Relay Dev Tools to look at the last few updates.

This can happen due to a newly created object which did not supply a specific field or, as mentioned above, an update which causes a new or changed relationship in the graph. In this case, use the “How do tell” tip from that section.

<DocsRating />

---

### Error Reference Unknown Field (`website/docs/error-reference/unknown-field.mdx`)

---
id: unknown-field
title: "Why Is My Field Not Found?"
slug: /error-reference/unknown-field/
description: Get help figuring out why a given field is not found.
keywords:
- no such field on type
- missing
- field
- type
- compilation
- error
---

import {FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
import DocsRating from '@site/src/core/DocsRating';

## [ERROR] Error in the project `some_project`: ✖︎ The type `Some_Type` has no field `some_unknown_field`.

### Field name typo

In case of a missing field in a type, the Relay compiler tries to find and suggest a field replacement. For example: ```Error in the project `some_project`: ✖︎ The type `UserInfo` has no field `mail`. Did you mean `email`?```

<FbInternalOnly>

### The field exists in another schema

Relay Compiler uses schemas in order to resolve types and their fields. The type's schema is determined by the file path and the mapping from file path to schema, which is configured in the "schema" or "schemaDir" properties of your Relay compiler config. If you expect this field to exist, make sure you're using the right schema.

:::note
At meta there are various project config files that are listed [here](https://www.internalfb.com/intern/wiki/Relay-team/Rust_compiler_resources/#where-are-the-project-co).
:::

</FbInternalOnly>

<DocsRating />

---

### Getting Started Babel Plugin (`website/docs/getting-started/babel-plugin.mdx`)

---
id: babel-plugin
title: Relay Babel Plugin
slug: /getting-started/babel-plugin/
description: Setting up Relay's Babel plugin
keywords:
- babel
---
# Babel Plugin

Relay requires a [Babel plugin](https://www.npmjs.com/package/babel-plugin-relay) to convert GraphQL to compiler-generated runtime artifacts. Depending upon what framework/bundler you are using, there may be a framework-specific plugin you can use:

- Vite: [vite-plugin-relay](https://github.com/oscartbeaumont/vite-plugin-relay)
- Next.js: [Relay config option](https://nextjs.org/docs/architecture/nextjs-compiler#relay)
- SWC: [@swc/plugin-relay](https://www.npmjs.com/package/@swc/plugin-relay)

If not, you can install the Babel plugin manually:

```sh
yarn add --dev babel-plugin-relay graphql
```

Add `"relay"` to the list of plugins in your `.babelrc` file:

```javascript
{
  "plugins": ["relay"]
}
```

Please note that the `"relay"` plugin should run before other plugins or presets to ensure the `graphql` template literals are correctly transformed. See Babel's [documentation on this topic](https://babeljs.io/docs/plugins/#pluginpreset-ordering).

---

### Getting Started Compiler Config (`website/docs/getting-started/compiler-config.mdx`)

---
id: compiler-config
title: Compiler Configuration
slug: /getting-started/compiler-config/
description: Schema description of the Relay Compiler configuration
keywords:
- compiler
- configuration
- config
hide_table_of_contents: false
---
import CompilerConfig from '@site/src/compiler-config/CompilerConfig';
import schema from '@compilerConfigJsonSchema';

## Compiler Config Options

For information about where the Relay compiler looks for its config file, or a minimal config, see the [Relay Compiler](./compiler.mdx#Configuration) page.

If you need more advanced options of the Relay Compiler Config, the exhaustive full schema can be found below. The shape of the Relay Compiler Config is given as `ConfigFile`. Note that while the shapes are documented in pseudo TypeScript, the compiler is parsing them in Rust so some subtle differences may exist.

:::tip
Install the [Relay VSCode extension](../editor-support.mdx) to get autocomplete, hover tips, and type checking for the options in your Relay config.
:::

<CompilerConfig schema={schema} definitions={schema.$defs} />

---

### Getting Started Compiler (`website/docs/getting-started/compiler.mdx`)

---
id: compiler
title: Relay Compiler
slug: /guides/compiler/
description: Relay guide to the compiler
keywords:
- compiler
---

Relay depends upon ahead-of-time compilation of GraphQL queries and fragments to generate artifacts that are used at runtime.

The Relay compiler is a command line tool that reads GraphQL fragments, queries, and mutations in your JavaScript code and generates TypeScript/Flow types and additional JavaScript code that gets included in your code via [Relay's Babel Plugin](./babel-plugin.mdx).

This guide explains configuring and using the Relay Compiler.

## Configuration

The Relay compiler will look for a Relay config in the following locations. It's up to you to decide which location works best for your project.

* `relay.config.json` in your project root
* `relay.config.(js/mjs/ts)` in your project root
* A `"relay"` key in your `package.json`

The Relay compiler config tells Relay things like where it can find your GraphQL schema and what language your code is written in. A minimal Relay compiler config looks like this:

```json title="relay.config.json"
{
  "src": "./src",
  "schema": "./schema.graphql",
  "language": "typescript"
}
```

:::tip
Install the [Relay VSCode extension](../editor-support.mdx) to get autocomplete, hover tips, and type checking for the options in your relay config.
:::

The compiler config is very powerful, and includes many specialized configuration options. For a full enumeration of the available options see the [Compiler Configuration](./compiler-config.mdx) page.


## Running the compiler

It is generally recommended that you add a `scripts` entry to your `package.json` to make it easy to run the Relay compiler for your project.

```json title="package.json"
{
  "scripts": {
    // change-line
    "relay": "relay-compiler"
  }
}
```

With this added you can run the Relay compiler like so:

```sh
npm run relay
```

### Watch mode

If you have [watchman](https://facebook.github.io/watchman) installed you can pass `--watch` to the Relay compiler to have it continue running and automatically update generated files as you edit your product code:

```sh
relay-compiler --watch
```

### Validate mode

Pass `--validate` to check whether any generated artifacts are out of date without writing anything to disk. The compiler exits with a non-zero code if any artifacts need to be updated. This is useful in CI to assert that generated files are committed and current:

```sh
relay-compiler --validate
```
### Disabling watchman

By default, Relay uses [watchman](https://facebook.github.io/watchman), if installed, for fast file discovery. To fall back to directory traversal instead, pass `--no-watchman`:

```sh
relay-compiler --no-watchman
```

### Codemods

The Relay compiler supports some built in codemods. Learn more in the [Codemods Guide](../guides/codemods.mdx).

### Document comparison (Experimental)

The Relay compiler can compare two GraphQL documents to determine if one is a subset of another. Learn more in the [Document Comparison Guide](../guides/document-comparison.mdx).

### Help

To see the full command-line reference run:

```sh
relay-compiler --help
relay-compiler <subcommand> --help
```

---

### Getting Started Lint Rules (`website/docs/getting-started/lint-rules.mdx`)

---
id: lint-rules
title: Relay ESLint Plugin
slug: /getting-started/lint-rules/
description: ESLint Plugin Relay
keywords:
- eslint
- lint
---

One of the unique features enabled by Relay is the ability to statically detect unused GraphQL fields. This can [categorically prevent](https://relay.dev/blog/2023/10/24/how-relay-enables-optimal-data-fetching/) the "append only query" problem that is a common dysfunction in many GraphQL clients.



This validation, and other helpful checks, are enabled by Relay's ESLint plugin [`eslint-plugin-relay`](https://www.npmjs.com/package/eslint-plugin-relay). **The Relay ESLint plugin is a key part of the Relay developer experience**.

## Installation

Assuming you have [ESLint](https://eslint.org/) already installed, you can add the Relay ESLint plugin to your project by running:

```sh
npm install --save-dev eslint-plugin-relay
```

Then update your ESLint configuration to include the plugin:

```js tile="eslint.config.js"
import relay from 'eslint-plugin-relay';

export default [
  // ... other ESlint Config
  {
    plugins: { relay },
    rules: relay.configs['ts-recommended'].rules,
  },
];
```

## Rule Descriptions

The following validation rules are included in the Relay ESLint plugin:

### `relay/unused-fields`
Ensures that every GraphQL field referenced is used within the module that includes it. This helps enable Relay's [optimal data fetching](https://relay.dev/blog/2023/10/24/how-relay-enables-optimal-data-fetching/).

### `relay/no-future-added-value`
Ensures code does not try to explicitly handle the `"%future added value"` enum variant which Relay inserts as a placeholder to ensure you handle the possibility that new enum variants may be added by the server after your application has been deployed.

### `relay/graphql-syntax`
Ensures each `graphql` tagged template literal contains syntactically valid GraphQL. This is also validated by the Relay Compiler, but the ESLint plugin can often provide faster feedback.

### `relay/graphql-naming`
Ensures GraphQL fragments and queries follow Relay's naming conventions. This is also validated by the Relay Compiler, but the ESLint plugin can often provide faster feedback.

### `relay/function-required-argument`
Ensures that `readInlineData` is always passed an explicit argument even though that argument is allowed to be `undefined` at runtime.

### `relay/hook-required-argument`
Ensures that Relay hooks are always passed an explicit argument even though that argument is allowed to be `undefined` at runtime.

### `relay/must-colocate-fragment-spreads`
Ensures that when a fragment spread is added within a module, that module directly imports the module which defines that fragment. This prevents the anti-pattern when one component fetches a fragment that is not used by a direct child component.
**Note**: This rule leans heavily on Meta's globally unique module names. It likely won't work well in other environments.

## Suppressing rules within graphql tags

The following rules support suppression within graphql tags:

- `relay/unused-fields`
- `relay/must-colocate-fragment-spreads`

Supported rules can be suppressed by adding `# eslint-disable-next-line relay/name-of-rule` to the preceding line:

```js
graphql`
  fragment foo on Page {
    # eslint-disable-next-line relay/must-colocate-fragment-spreads
    ...unused1
  }
`;
```

Note that only the `eslint-disable-next-line` form of suppression works. `eslint-disable-line` doesn't currently work until graphql-js provides support for [parsing Comment nodes](https://github.com/graphql/graphql-js/issues/2241) in their AST.

## Contributing

If you wish to contribute to the Relay ESLint plugin, you can find the code on GitHub at [relay/eslint-plugin-relay](https://github.com/relayjs/eslint-plugin-relay/).

---

### Getting Started Production (`website/docs/getting-started/production.mdx`)

---
id: production
title: Production Setup
slug: /getting-started/production/
description: Setting up Relay for production use
keywords:
- production
---

Getting the most out of Relay in production requires a few extra steps. This page covers a list of best practices for taking Relay to production.

## Persisted Queries (Trusted Documents)

One of GraphQL's key innovations is that it enables clients to define arbitrary queries. While this unlocks a lot of flexibility, it also opens the doors to abuse. Scrapers can use GraphQL to scrape data from your site, and malicious users can use GraphQL to send large requests to your server that cause a denial of service. To prevent this, we recommend using [Persisted Queries](../guides/persisted-queries.mdx) also know as [Trusted Documents](https://benjie.dev/graphql/trusted-documents).

With Persisted Queries, the set of queries that the client can send is locked in at build time. This means that scrapers and malicious attackers are limited to sending only the queries used by the client, just like REST. It also has the added benefit that the client code only needs to include a single id for each query rather than the whole query text.



## Relay Lint Rules

A key principle of Relay is data colocation where each component defines its own data dependencies. It's critical to [How Relay Enables Optimal Data Fetching](https://relay.dev/blog/2023/10/24/how-relay-enables-optimal-data-fetching/). However, this is often unintuitive for developers who are used to fetching data in a single query. Relay's ESLint rules can help enforce this pattern by ensuring no component fetches fields which it does not itself use.

We recommend using the [`eslint-plugin-relay`](https://github.com/relayjs/eslint-plugin-relay), especially the `relay/unused-fields` rule.

Learn how to install them: [Relay ESLint Plugin](./lint-rules.mdx).

## Running the Relay Compiler in CI

We recommend committing Relay's generated artifacts to source control along with your application code. This ensures generated types are present without needing an additional build, and allows for inspection of generated artifacts in code review. To ensure the generated artifacts are always in sync with the source code, we recommend running the Relay compiler in CI and ensuring it does not change any generated files. A example bash script which checks for changes can be found [here](https://github.com/facebook/relay/blob/0414c9ad0744483e349e07defcb6d70a52cf8b3c/scripts/check-git-status.sh).

---

### Getting Started Quick Start (`website/docs/getting-started/quick-start.mdx`)

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

---

### Glossary Glossary (`website/docs/glossary/glossary.mdx`)

---
id: glossary
title: Glossary
slug: /glossary/
description: Relay terms glossary
keywords:
- glossary
---

import DocsRating from '@site/src/core/DocsRating';
import {FbInternalOnly, OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## 3D

Data-Driven Dependencies. Facebook's way of including the code to render a particular component if and only if it will actually be rendered. Canonical use cases are

* **Fields that are typically null**, and which are only rendered when not null.
* **Unions**. For example, the core news feed item has many different variants, each of which is a separate React component. Which one we render depends on the data (i.e. is "data-driven"). On a given feed, it is likely that most variants will not be rendered, and need not be downloaded.
* **Component can have different rendering strategies, depending on the data.**

<FbInternalOnly>

See the [@match](#match) directive, [@module](#module) directive and [the 3D guide](../guides/data-driven-dependencies/server-3d).

</FbInternalOnly>

<OssOnly>

See the [@match](#match) directive and the [@module](#module) directive.

</OssOnly>

## Abstract Type

GraphQL unions and interfaces are abstract types. See [interface](#interface-graphql).

## Abstract Type Refinement

See [type refinement](#type-refinement). If type refinement is a way of conditionally including fields if a type implements a particular concrete type (such as `... on User { name }`), abstract type refinement refers to conditionally including fields if a type implements a particular abstract type (i.e. interface). So, `... on Actor { field }`.

## @arguments

A [directive](#directive) that modifies a [fragment spread](#fragment-spread) and is used to pass arguments (defined with [`@argumentDefinitions`](#argumentdefinitions)) to that fragment.

```graphql
...Story_story @arguments(storyId: "1234")
```

## @argumentDefinitions

A directive that modifies a fragment definition and defines the names of the local arguments that the fragment can take, as well as their type.

```graphql
fragment Store_story on Story
  @argumentDefinitions(storyId: {type: "ID!"}) {
  # etc
}
```

If a variable is used in a fragment but not included in an `@argumentDefinitions` directive, Relay will require that the fragment is only spread in queries which declare these variables, or in fragments which ultimately are spread in such a query.

Compare with [variables](#variables) and see the [relevant section](../guided-tour/rendering/variables) in the guided tour.

## Artifact

Files that are generated by the [Relay compiler](../getting-started/compiler.mdx), typically ending in `.graphql.js`.

<FbInternalOnly>

See [a guide to Relay artifacts](https://www.internalfb.com/intern/wiki/Relay-team/generated-artifacts/).

</FbInternalOnly>

## AST

Abstract Syntax Tree. In Relay, there are two types of ASTs, [normalization](#normalization-ast) and [reader](#reader-ast) ASTs.

The default export of a `.graphql.js` file is an AST.

The Relay compiler parses and transforms GraphQL literals, and generates Relay ASTs (see [artifact](#artifact)). Doing this work at compile time allows the Relay runtime to be faster.

## Availability

The concept of availability refers to whether there is enough non-stale, non-invalidated data in the store to fulfill a particular request immediately, or whether a request to server needs to be made in order to fulfill that request.

## Babel Transform

A build-time transformation of the Javascript codebase, which turns calls to

```javascript
graphql`...`
```

into `require(NAME_OF_GENERATED_ARTIFACT)` calls. See [Babel Plugin](../getting-started/babel-plugin.mdx).

## Client Schema Extension

[The GraphQL spec](https://spec.graphql.org/June2018/#sec-Schema-Extension) allows you to define new types, new fields on types, new directives, etc. locally.

Relay supports adding types and fields in client schema extension files. Developers use this feature to add fields that contain purely local state that is associated with items on the graph. For example, an `is_selected` field on a `User`.

## CacheConfig

A value used to control how a query's response may be cached. Ultimately passed to `environment.execute`.

## Check

One of the core functions of the store. Given an operation, determines whether the store has all of the data necessary to render that operation. Calls `DataChecker.check`, which synchronously starts with the root node associated with the operation and walks the data in the store.

In practice, exposed as a method on `environment`.

In conjunction with the fetch policy, used by `loadQuery` (and other methods) to determine whether it is necessary to make a network request call to fulfill a query.

## Commit

After receiving a network response, the payload is committed, or written to the store.

Commit is also the verb used to describe initiating a mutation and writing its data to the store.

## Compiler

The piece of code which scans your Javascript files for `graphql` tagged nodes and generates the appropriate files (`.graphql.js` files, `$Parameters.js` files, etc.)

The generated output from the compiler is committed and checked into the repository.

## Concrete Request

An Abstract Syntax Tree representing a query, subscription or mutation.

The default export of a `.graphql.js` file corresponding to a query, subscription or mutation.

In addition, calls to `graphql`...`` are turned into concrete requests at build time via the Relay Babel transform.

**See the important safety notes at Preloadable Concrete Request.**

## Config

A [file or javascript object](../getting-started/compiler-config.mdx) which controls, among other things, which files are scanned by the Relay [compiler](#compiler) for your project.

## @connection

A directive which declares that a field implements the [connection](#connection) spec.

## Connection

<FbInternalOnly>

A field implementing the [connection spec](https://relay.dev/graphql/connections.htm). See <a href="https://www.internalfb.com/intern/wiki/Graphql-connections-for-hack-developers/Connection-spec/">here</a> for more details on the spec, and the section of the guided tour on <a href="../guided-tour/list-data/pagination/">rendering list data and pagination</a>.

</FbInternalOnly>

<OssOnly>

A field implementing the [connection spec](https://relay.dev/graphql/connections.htm). See the section of the guided tour on <a href="../guided-tour/list-data/pagination/">rendering list data and pagination</a>.

</OssOnly>

See also [`usePaginationFragment`](../api-reference/use-pagination-fragment).

## Container

A term for a higher order component that provided a child component with the data from queries and fragments. Associated with Relay Modern.

You should use the Relay hooks API when possible.

## Data Checker

A class exposing a single method, `check`, which synchronously starts with the root node associated with the operation and walks the data in the store. It determines whether the data in the store suffices to fulfill a given operation.

Called by `store.check`.

## DataID

The globally-unique identifier of a record. Can be generated on the client with [missing field handlers](#missing-field-handler). Usually corresponds to an Ent's ID (if available), but guaranteed to equal the value of the `__id` field.

[`updater`](#updater) and [`optimisticUpdater`](#optimisticupdater) functions are passed instances of [`RelaySourceSelectorProxy`](#recordproxy). Calling `.get(id)` with the DataID on a `RelaySourceSelectorProxy` will look up that item in the store, and return a proxy of it.

## Data Masking

Refers to the idea that a component should not be able to access any data it does declare in its fragment or query, even inadvertently. This prevents accidental coupling of data between components, and means that every component can be refactored in isolation. It negates the risk that removing a field in a child component will accidentally break a different component, allowing components to *move fast, with stable infrastructure*.

Also refers to the practice of hiding the data of child components from their parents, in keeping with the idea.

In Relay, a query declared like `query FooQuery { viewer { ...subcomponent_``viewer_name } }` will not be able to access the data declared by `subcomponent_viewer_name` without access to the `ReaderFragment` representing the `subcomponent_viewer_name` fragment.

See the [Thinking in Relay guide](../principles-and-architecture/thinking-in-relay#data-masking).

## @defer

A directive which can be added to a fragment spread or inline fragment to avoid blocking on that fragment's data. For more detail refer to GraphQL's [documentation on the @defer directive](https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.mdx#defer).

<FbInternalOnly>

See [Incremental Data Delivery](https://www.internalfb.com/intern/staticdocs/relay/docs/guides/incremental-data-delivery/).

</FbInternalOnly>

## Definition

In the compiler, a definition refers to the text within a GraphQL literal where an operation or fragment was defined.

## Descriptor

Can refer to an `OperationDescriptor` or `RequestDescriptor`. Descriptors are types used internally to the Relay codebase, and generally, refer to an object containing the minimum amount of information needed to uniquely identify an operation or request, such as (for a `RequestIdentifier`), a node, identifier and variables.

## DevTools

An awesome Chrome extension for debugging Relay network requests, the Relay store and Relay events. Helpful for answering questions like "Why am I not seeing the data I expect to see?" "Why did this component suspend?" etc.

See the [documentation](https://relay.dev/docs/debugging/relay-devtools/).

## Document

In the compiler, a Document refers to a GraphQL literal that contains one or more operation or fragment [definitions](#definition). Relay requires that GraphQL literals in JavaScript files contain a single definition.

## Directive

A special instruction, starting with `@` and contained in a `graphql` literal or graphql file, which provides special instructions to the Relay compiler or to the server. Examples include `@defer`, `@stream` and `@match`.

## Disposable

Any object which contains a `.dispose` method which takes no parameters and provides no return value. Many objects in Relay (such query references and entrypoint references) and the return value of many methods (such as calls to `.subscribe` or `.retain`) are disposables.

## Entrypoint

A lightweight object containing information on the components which need to be loaded (as in the form of calls to `JSResource`) and which queries need to be loaded (in the form of preloadable concrete requests) before a particular route, popover or other piece of conditionally loaded UI can be rendered.

All queries which are required for the initial rendering of a piece of UI should be included in that UI's entrypoint.

Entrypoints can contain queries and other entrypoints.

See also [preloadable concrete request](#preloadable-concrete-request) and [JSResource](#jsresource).

## Environment

An object bringing together many other Relay objects, most importantly a store and a network. Also, includes a publish queue, operation loader, scheduler and [missing fields handlers](#missing-field-handler).

Set using a `RelayEnvironmentProvider` and passed down through React context.

All non-internal Relay hooks require being called within a Relay environment context.

## Execute

Executing a query, mutation or subscription (collectively, an operation) roughly means "create a lazy observable that, when subscribed to, will make a network request fulfilling the operation and write the returned data to the store."

A variety of `execute` methods are exposed on the Relay environment.

## Fetch Policy

A string that determines in what circumstances to make a network request in which circumstances to fulfill the query using data in the store, if available. Either `network-only`, `store-and-network`, `store-or-network` or `store-only`. (Some methods do not accept all fetch policies.)

## Field

Basically, anything you can select using a query, mutation, subscription or fragment. For example, `viewer`, `comment_create(input: $CommentCreateData)` and `name` are all fields.

The GraphQL schema comprises many fields.

## Fragment

Fragment is an overloaded term, and has at least two distinct meanings in Relay.

### Fragments as a GraphQL concept

The fundamental reusable unit of GraphQL. Unlike queries, subscriptions and mutations, fragments cannot be queried on their own and must be embedded within a request.

Fragments can be spread into queries, mutations, subscriptions and other fragments.

Fragments can be standalone (as in `fragment Component_user on User { name }`) or inline, as in the `... on User { name }` in `query MyQuery { node(id: $id) { ... on User { name } } }`.

Fragments are always defined on a particular type (`User` in the example), which defines what fields can be selected within it.

### Fragments within Relay

Within Relay, a fragment refers to the fields that are read out for a given fragment/operation. The term is also used colloquially to refer to reader ASTs. So, e.g. the following query and fragment might have identical reader ASTs:

```graphql
query Foo {
  actor { name }
}
```

```
fragment Bar on Query {
  actor { name }
}
```

## Fragment Identifier

A string, providing enough information to provide the data for a particular fragment. For example:

`1234{"scale":2}/Story_story/{"scale":2}/"4567"`

This identifies by its persist ID (`1234`), followed by the variables it accepts, followed by the `Story_story` fragment (which does not have a persist id) and the variables it uses, followed by the Data ID (likely, the `id` field) of whatever Story happened to be referenced.

## Fragment Reference

A parameter passed to `useFragment`. Obtained by accessing the value onto which a fragment was spread in another [query](#query), fragment, subscription or mutation. For example,

```javascript
const queryData = usePreloadedQuery(
  graphql`query ComponentQuery { viewer { account_user { ...Component_name } } }`,
  {},
);

// queryData.viewer is the FragmentReference
// Though this would usually happen in another file, you can
// extract the value of Component_name as follows:
const fragmentData = useFragment(
  graphql`fragment Component_name on User { name }`,
  queryData?.viewer?.account_user,
);
```

Just like a query reference and a graphql tagged literal describing a query (i.e. a concrete request) can be used to access the data from a query, a fragment reference and a graphql tagged literal describing a fragment (i.e. a reader fragment) can be used to access the data referenced from a fragment.

## Fragment Resource

An internal class supporting lazily loaded queries. Exposes two important methods:

* `read`, which is meant to be called during a component's render phase. It will attempt to fulfill a query from the store (by calling `environment.lookup`) and suspend if the data is not available. It furthermore writes the results from the attempted read (whether a promise, error or result) to an internal cache, and updates that cached value when the promise resolves or rejects.
* `subscribe`, which is called during the commit phase, and establishes subscriptions to the Relay store.

If the component which calls `.read` successfully loads a query, but suspends on a subsequent hook before committing, the data from that query can be garbage collected before the component ultimately renders. Thus, components which rely on `FragmentResource` are at risk of rendering null data.

Compare to [query resource](#query-resource).

## Fragment Spread

A fragment spread is how one fragment is contained in a query, subscription, mutation or other fragment. In the following example, `...Component_name` is a fragment spread:

```graphql
query ComponentQuery {
  viewer {
    account_user {
      ...Component_name
    }
  }
}
```

In order for a fragment to be spread in a particular location, the types must match. For example, if `Component_name` was defined as follows: `fragment Component_name on User { name }`, this spread would be valid, as `viewer.account_user` has type `User`.

## Garbage Collection

Relay can periodically garbage collect data from queries which are no longer being retained.

See more information in the [guided tour](https://relay.dev/docs/guided-tour/reusing-cached-data/presence-of-data/#garbage-collection-in-relay).

## GraphQLTaggedNode

This is the type of the call to

```js
graphql`...`
```

It is the union of ReaderFragment, ReaderInlineDataFragment, ConcreteRequest, and ConcreteUpdatableQuery.

<OssOnly>

Note that Flow can be configured to understand that the type of a GraphQL literal is the type of the default export of the generated `.graphql.js` file.

</OssOnly>

<FbInternalOnly>

Note that Flow is configured to understand that the type of a GraphQL literal is the type of the default export of the generated `.graphql.js` file.

</FbInternalOnly>

## ID

Relay treats ids specially. In particular, it does the following two things:

* The compiler automatically adds a selection of the `id` field on every type where the `id` field has type `ID` or `ID!`.
* When [normalizing](#normalization) data, if an object has an `id` property, that field is used as its ID in the store.

There are types in the schema where the `id` field does not have type `ID` or `ID!` (e.g. has the type `string` or `number`). If a user selects this field themselves, this field is used as an id. This is unexpected and incorrect behavior.

## @include

A directive that is added to fields, inline fragments and fragment spreads, and allows for conditional inclusion. It is the opposite of the [`@skip`](#skip) directive.

In the compiler, the `@include`/`@skip` directives are treated specially, and produce `Condition` nodes.

## @inline

A directive that applies to fragments which enables developers to pass masked data to functions that are executed outside of the React render phase.

Normally, data is read out using `useFragment`. However, this function can only be called during the render phase. If store data is needed outside of the render phase, a developer has several options:

* read that data during the render phase, and pass it to the function/have the function close over that data. (See also [#relay])
* pass a reference to an `@inline` fragment, which can then be accessed (outside of the render phase) using the `readInlineData` function.

This directive causes them to be read out when the parent fragment is read out, and unmasked by the call to `readInlineData`.

## Interface (GraphQL)

An *Interface* is an abstract type that includes a certain set of fields that a type must include to implement the interface.

You can spread a fragment on an interface onto a concrete type (for example `query MyQuery { viewer { account_user { ...on Actor { can_viewer_message } } }`) or a fragment on a concrete type onto an interface (for example `query MyQuery { node(id: 4) { ... on User { name } } }`). You are no longer allowed to spread a fragment on an interface onto an interface.

See also abstract type refinement.

## Invalidation

In certain cases, it is easy to determine the outcome of a mutation. For example, if you "like" a Feedback, the like count will increment and `viewer_did_like` will be set to true. However, in other cases, such as when you are blocking another user, the full impact on the data in your store is hard to determine.

For situations like these, Relay allows you to invalidate a record (or the whole store), which will cause the data to be re-fetched the next time it is rendered.

See the [section in the guide](https://relay.dev/docs/guided-tour/reusing-cached-data/staleness-of-data/).

## JSResource

A lightweight API for specifying that a React component should be loaded on demand, instead of being bundled with the first require (as would be the case if you imported or required it directly.)

This API is safe to use in entrypoint files.

<OssOnly>

See [the npm module](https://www.npmjs.com/package/jsresource).

</OssOnly>

## Lazy Loading

A query or entry point is lazy loaded if the request for the data occurs at render time.

Lazy loaded queries and entry points have performance downsides, are vulnerable to being over- and under-fetched, and can result in components being rendered with null data. They should be avoided.

## Linked Record

A linked record is a record that is directly accessible from another record. For example, in the query `query MyQuery { viewer { account_user { active_instant_game { id } } } }`, `active_instant_game` (which has the type `Application` is a linked record of `account_user`.

A linked record cannot be queried by itself, but must be queried by selecting subfields on it.

Compare to [value](#value).

## Literal

A GraphQL literal is a call to

```javascript
graphql`...`
```

in your code. These are pre-processed, and replaced at build time with a [GraphQLTaggedNode](#graphqltaggednode) containing an [AST](#ast) representation of the contents of the literal.

## @live

A docblock tag that can be added to mark a Relay resolver as live. To learn more, refer to the [live fields section](https://relay.dev/docs/guides/relay-resolvers/live-fields/) of the Relay resolver documentation.

<FbInternalOnly>

## @live_query
A directive used on GraphQL queries that enables data updates to be delivered over time without any custom server-side code. This directive provides a more efficient and maintainable alternative to polling (running the same query over and over again).

Live queries are a feature of GraphQL within Meta and supported by the [Real-Time GraphQL team](https://www.internalfb.com/omh/view/real_time_graphql/oncall_profile). To learn more about GraphQL live queries, refer to the [GraphQL Live Queries wiki](https://www.internalfb.com/intern/wiki/GraphQL_Live_Queries/Overview/).

You can learn more about how to use @live_query with Relay on Web with server-polling [here](https://www.internalfb.com/intern/wiki/GraphQL_Live_Queries/Live_Queries_for_Relay/) and client-polling [here](https://www.internalfb.com/intern/wiki/GraphQL_Live_Queries/Live_Queries_for_Relay_(Client_Polling)/).
</FbInternalOnly>

## Lookup

One of the main methods exposed by the Relay store. Using a [reader selector](#reader-selector), traverses the data in the store and returns a [snapshot](#snapshot), which contains the data being read, as well as information about whether data is missing and other pieces of information. Also exposed via the Relay environment.

Calls [`Reader.read`](#reader).

## @match

A directive that, when used in combination with [@module](#module), allows users to download specific JS components alongside the rest of the GraphQL payload if the field decorated with @match has a certain type. See [3D](#3d).

## MatchContainer

A component that renders the component returned in conjunction with a field decorated with the [@match](#match) directive. See [3D](#3d).

## Missing Field Handler

A function that provides a [DataID](#dataid) for a field (for singular and plural linked fields) and default values (for scalar fields).

For example, you may have already fetched an item with id: 4, and are executing a query which selects `node(id: 4)`. Without a missing field handler, Relay would not know that the item with id: 4 will be returned by `node(id: 4)`, and would thus attempt to fetch this data over the network. Providing a missing field handler can inform Relay that the results of this selection are present at id: 4, thus allowing Relay to avoid a network request.

`getRelayFBMissingFieldHandlers.js` provides this and other missing field handlers.

## @module

A directive that, when used in combination with [@match](#match), allows users to specify which JS components to download if the field decorated with @match has a certain type. See [3D](#3d).

## Module

A ["Module"](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) refers to a React component or a piece of JavaScript code.

In the context of Relay, modules can by dynamically loaded with the @module directive. This directive allows developers to specify which JavaScript components should be downloaded (from a CDN for example) based on the type of a field decorated with the @match directive. This approach is part of Relay's [data-driven dependencies](#3d) strategy, where components are only loaded if they are actually needed for rendering.

## Mutation

A mutation is a combination of two things: a mutation on the backend, followed by query against updated data.

<FbInternalOnly>

See the [guide on mutations](../guided-tour/updating-data/graphql-mutations), and [this article](https://www.internalfb.com/intern/wiki/Graphql-for-hack-developers/mutation-root-fields/) on defining mutations in your hack code.

</FbInternalOnly>

<OssOnly>

See the [guide on mutations](../guided-tour/updating-data/graphql-mutations).

</OssOnly>

## Mutation Root Query

The root object of a mutation query. In an `updater` or `optimisticUpdater`, calling `store.getRootField('field_name')` will return the object from the mutation root query named `field_name`.

The fields exposed on this object are **not** the same as those available for queries, and differ across mutations.

## Network

Relay environments contain a `network` object, which exposes a single `execute` function. All network requests initiated by Relay will go through this piece of code.

This provides a convenient place to handle cross-cutting concerns, like authentication and authorization.

## Node

A Node is an object that implements the Node interface in GraphQL, which requires an `id` field of type `ID`. This is part of the [Global Object Identification specification](https://relay.dev/graphql/objectidentification.htm) that provides a standardized way to fetch and identify objects in a GraphQL schema.

In Relay, the Node interface is fundamental to how data normalization and caching work. When Relay encounters an object with an `id` field, it uses that ID as the key for storing the object in its normalized cache. This enables efficient data deduplication, updates, and garbage collection.

Nodes can be refetched using the `node` field on the Query root type by passing their global ID: `query { node(id: "abc123") { ... } }`. This allows Relay to fetch data for any object implementing the Node interface without needing to know the specific field path to that object.

## Normalization

Normalization is the process of turning nested data (such as the server response) and turning it into flat data (which is how Relay stores it in the store.)

See the [response normalizer](#response-normalizer).

## Normalization AST

An [AST](#ast) that is associated with an [operation](#operation) that (in combination with [variables](#variables)) can be used to:
* write a network payload to the store,
* write an optimistic response to the store,
* determine whether a query can be fulfilled from data in the store, and
* determine which records in the store are reachable (used in [garbage collection](#garbage-collection)).

Unlike the [reader AST](#reader-ast), the normalization AST includes information on the contents of nested fragments.

The generated artifact associated with an operation (e.g. `FooQuery.graphql.js`) contains both a normalization AST and a reader AST.

## Normalization Selector

A selector defines the starting point for a traversal into the graph for the purposes of targeting a subgraph, combining a GraphQL fragment, variables, and the Data ID for the root object from which traversal should progress.

## Notify

A method exposed by the store which will notify each [subscriber](#subscribe) whose data has been modified. Causes components which are rendering data that has been modified to re-render with new data.

## Observable

The fundamental abstraction in Relay for representing data that may currently be present, but may also only be available in the future.

Observables differ from promises in that if the data in an observable has already been loaded, you can access it synchronously as follows:

```javascript
const completedObservable = Observable.from("Relay is awesome!");
let valueFromObservable;
observable.subscribe({
  next: (value) => {
    valueFromObservable = value;
    /* this will execute in the same tick */
  },
});
console.log(valueFromObservable); // logs out "Relay is awesome!"
```

This is advantageous, as it allows Relay hooks to not suspend if data is already present in the store.

In Relay, observables are a partial implementation of [RxJS Observables](https://rxjs-dev.firebaseapp.com/guide/observable).

## Operation

In [GraphQL](https://spec.graphql.org/June2018/#sec-Language.Operations), a query, subscription or mutation.

In Relay, every operation also has an associated [fragment](#fragments-within-relay). So, an accurate mental model is that operations are fragments whose [type condition](#type-condition) is that they are on [Query/Mutation/Subscription](#root-type) and for which Relay knows how to make a network request.

## Operation Descriptor

Colloquially, an operation descriptor is an operation and variables.

The operation descriptor flowtype contains the three pieces of information that Relay needs to work with the data: [a reader selector](#reader-selector), a [normalization selector](#normalization-selector) and a [request descriptor](#request-descriptor).

The variables are filtered to exclude unneeded variables and are populated to include default values for missing variables, thus ensuring that requests that differ in irrelevant ways are cached using the same request ID.

## Operation Mock Resolver

A function taking an operation descriptor and returning a network response or error, used when testing.

## Operation Tracker

The Relay Operation Tracker is a component within the Relay runtime that manages and tracks the lifecycle of [operations](#operation) (queries, subscriptions, and mutations), in the Relay store. It maintains mappings between operations and affected data owners, manages promises for asynchronous updates, and resolves dependencies by notifying subscribers when data changes, ensuring components render with the latest data. For more implementation details of the Operation Tracker, see the [OSS code here](https://github.com/facebook/relay/blob/main/packages/relay-runtime/store/RelayOperationTracker.js).

## Optimistic Update

An Optimistic Update in Relay is a technique used to immediately reflect the expected outcome of a mutation in the UI before the server response is received.

This approach enhances user experience by providing instant feedback for actions, such as liking a post, without waiting for the server to confirm the change.

Optimistic updates assume the mutation will succeed and temporarily update the store with the anticipated result. If the mutation fails, the optimistic update is rolled back to maintain data consistency. This is typically achieved by providing an optimisticResponse in the mutation configuration, which specifies the expected changes to the data.

See the [documentation on optimistic updates](../guided-tour/updating-data/graphql-mutations/#optimistic-updates) for examples of how to use this feature.

## Optimistic Updater

An Optimistic Updater in Relay is a function that allows developers to imperatively modify the store's data in anticipation of a mutation's success.

Unlike [optimistic responses](../guided-tour/updating-data/graphql-mutations/#optimistic-response), which are declarative, optimistic updaters provide more control and flexibility, enabling updates to data not directly selected in the mutation or complex changes that cannot be handled by declarative mutation directives.

Optimistic updaters are executed when a mutation is triggered and are rolled back if the mutation fails. They are particularly useful for scenarios where multiple optimistic responses affect the same store value, and fine grained control is needed by the developer to ensure that the store remains consistent.

See the documentation on [optimistic updaters](../guided-tour/updating-data/graphql-mutations/#optimistic-updaters) for examples of how to use them.

## Pagination

Querying a list of data (a [connection](#connection)) in parts is known as pagination.

See the [graphql docs](https://graphql.org/learn/pagination/) and our [guided tour](../guided-tour/list-data/pagination).

## Payload

The value returned from the GraphQL server as part of the response to a request.

## Plural Field

A field for which the value is an array of [values](#value) or [records](#record).

## @preloadable

A directive that modifies queries and which causes Relay to generate `$Parameters.js` files and preloadable concrete requests. Required if the query is going to be used as part of an entry point.

## Preloadable Concrete Request

A small, lightweight object that provides enough information to initiate the query and fetch the full query AST (the `ConcreteRequest`.) This object will only be generated if the query is annotated with `@preloadable`, and is the default export of `$parameters.js` files. It is only generated for queries which are annotated with `@preloadable`.

Unlike concrete requests (the default export of `.graphql.js` files), preloadable concrete requests are extremely light weight.

Note that entrypoints accept either preloadable concrete requests or concrete requests in the `.queries[queryName].parameters` position. However, ***because a concrete request is not a lightweight object, you should only include preloadable concrete requests here.***

Note also that preloadable queries have `id` fields, whereas other queries do not.

## Preloadable Query Registry

A central registry which will execute callbacks when a particular Query AST (concrete request) is loaded.

Required because of current limitations on dynamically loading components in React Native.

## Project

For Relay to process a file with a GraphQL literal, it must be included in a project. A project specifies the folders to which it applies and the schema against which to evaluate GraphQL literals, and includes other information needed by the Relay compiler.

<FbInternalOnly>

Projects are defined in a single [config](#config) file, found [here](https://www.internalfb.com/intern/diffusion/WWW/browse/master/scripts/relay/compiler-rs/config.www.json) and [here](https://www.internalfb.com/intern/diffusion/FBS/browse/master/xplat/relay/compiler-rs/config.xplat.json).

</FbInternalOnly>

## Publish

One of the main methods exposed by the `store`. Accepts a [record source](#record-source), from which the records in the store are updated. Also updates the mapping of which records in the store have been updated as a result of publishing.

One or more calls to `publish` should be followed by a call to [`notify`](#notify).

## Publish Queue

A class used internally by the environment to keep track of, apply and revert pending (optimistic) updates; commit client updates; and commit server responses.

Exposes mutator methods like `commitUpdate` that only add or remove updates from the queue, as well as a `run` method that actually performs these updates and calls `store.publish` and `store.notify`.

## Query

A [GraphQL query](https://graphql.org/learn/queries/) is a request that can be sent to a GraphQL server in combination with a set of [variables](../guided-tour/rendering/variables), in order to fetch some data. It consists of a [selection](#selection) of fields, and potentially includes other [fragments](#fragment).

## Query Executor

A class that normalizes and publishes optimistic responses and network responses from a network observable to the store.

After each response is published to the store, `store.notify` is called, updating all components that need to re-render.

Used by `environment` in methods such as `execute`, `executeWithSource` and `executeMutation`, among others.

## Query Reference

A Query Reference is an opaque token that represents a query that we have started fetching, but may not have been returned by the network yet. It's returned by functions like `loadQuery` and serves as an identifier for which query we want to render.

Query references are intentionally opaque to the user - they don't expose the query's internal state or data directly. Instead, they are passed to `usePreloadedQuery` to access the data from a preloaded query.

The query reference pattern enables efficient data loading by allowing queries to be initiated early (such as in response to user interactions like hovering or route changes) and then consumed later when the component actually renders.

Query references are disposable objects - they should be disposed of when no longer needed to prevent memory leaks and allow proper cleanup of network requests and subscriptions.

## Query Resource

A class for helping with lazily loaded queries and exposing two important methods: `prepare` and `retain`.

* `prepare` is called during a component's render method, and will either read an existing cached value for the query, or fetch the query and suspend. It also stores the results of the attempted read (whether the data, a promise for the data or an error) in a local cache.
* `retain` is called after the component has successfully rendered.

If the component which calls `.prepare` successfully loads a query, but suspends on a subsequent hook before committing, the data from that query can be garbage collected before the component ultimately renders. Thus, components which rely on `QueryResource` are at risk of rendering null data.

Compare to [fragment resource](#fragment-resource).

## `@raw_response_type`

A directive added to queries which tells Relay to generate types that cover the `optimisticResponse` parameter to `commitMutation`.

See the [guided tour on updating data](../guided-tour/updating-data/graphql-mutations/#optimistic-response) for more.

## Reader

A core component of the Relay runtime responsible for reading data from the store. The Reader traverses the normalized data in the store using a [reader AST](#reader-ast) and constructs the denormalized data structure that matches the shape expected by components.

The Reader is called by the store's [lookup](#lookup) method and is fundamental to how Relay provides data to React components. It handles data masking by only exposing the fields that were explicitly selected in fragments and queries, ensuring components can only access the data they declared dependencies for.

The Reader also manages missing data detection, determining when insufficient data is available in the store to fulfill a request, which helps Relay decide when network requests are necessary.

## Reader AST

An [AST](#AST) that is used to read the data selected in a given fragment.

Both [operations](#operation) and [fragments](#fragment) have reader ASTs.

A reader AST contains information about which fragments are spread at a given location, but unlike a [normalization AST](#normalization-ast), does not include information about the fields selected within these fragments.

## Reader Fragment

TODO

See [GraphQLTaggedNode](#graphqltaggednode).

## Reader Selector

An object containing enough information for the store to traverse its data and construct an object represented by a query or fragment. Intuitively, this "selects" a portion of the object graph.

See also [lookup](#lookup).

## Record

A record refers to any item in the Relay [store](#store) that is stored by [ID](#id). [Values](#value) are not records; most everything else is.

## Record Source

An abstract interface for storing [records](#record), keyed by [DataID](#dataid), used both for representing the store's cache for updates to it.

## Record Source Selector Proxy

See [record proxy](#record-proxy).

## Record Proxy

See the [store documentation](../api-reference/store).

## Ref Counting

The pattern of keeping track of how many other objects can access a particular object, and cleaning it up or disposing of it when that number reaches zero. This pattern is implemented throughout the Relay codebase.

## Reference Marker

The Relay Reference Marker is a component within the Relay runtime responsible for traversing the data graph and marking references to data that should be retained in the Relay store. It ensures data consistency by preventing premature garbage collection of data required for operations or fragments. The marker handles various data selections, manages variables, and interacts with the operation loader to process module imports, ensuring that all necessary data dependencies are retained.
See the [OSS code](https://github.com/facebook/relay/blob/main/packages/relay-runtime/store/RelayReferenceMarker.js) for implementation details.

## @refetchable

A directive that modifies a fragment, and causes Relay to generate a query for that fragment.

This yields efficiency gains. The fragment can be loaded as part of a single, larger query initially (thus requiring only a single request to fetch all of the data), and yet refetched independently.

## @relay

A directive that allows you to turn off data masking and is used on plural types.

See [the documentation](../api-reference/graphql-and-directives/#relaymask-boolean).

## Relay Classic

An even older version of Relay.

## Relay Hooks

The easiest-to-use, safest Relay API. It relies on suspense, and is safe to use in React concurrent mode.

You should not write new code using Relay Classic or Relay Modern.

## Relay Modern

An older version of Relay. This version of Relay had an API that was heavily focused on Containers.

## Relay Resolvers

Relay Resolvers is an experimental Relay feature which enables modeling derived state as client-only fields in Relay’s GraphQL graph.

See also [the Relay Resolvers Introduction](../guides/relay-resolvers/introduction.mdx).

## Release Buffer

As queries are released (no longer [retained](#retain)), their root nodes are stored in a release buffer of fixed size, and only evicted by newly released queries when there isn't enough space in the release buffer. When Relay runs garbage collection, queries that are present in the release buffer and not disposed.

The size of the release buffer is configured with the `gcReleaseBufferSize` parameter.

## `@required`

A Relay directive that makes handling potentially `null` values more ergonomic.

See also [the `@required` guide](../guides/required-directive/).

## Request

A request refers to an API call made over the network to access or mutate some data, or both.

A query, when initiated, may or may not involve making a request, depending on whether the query can be fulfilled from the store or not.

## Request Descriptor

An object associating a [concrete request](#concrete-request) and [variables](#variables), as well as a pre-computed request ID. The variables should be filtered to exclude unneeded variables and are populated to include default values for missing variables, thus ensuring that requests that differ in irrelevant ways are cached using the same request ID.

## Resolver

An overloaded term, mostly referring to virtual fields, but also occasionally referring to other things.

### When describing a field

A resolver field is a "virtual" field that is backed by a function from a fragment reference on the same type to some arbitrary value.

A live resolver is a "virtual" field that is backed by an external data source. e.g. one might use an external resolver to expose some state that is stored in local storage, or in an external Flux store.

### Other meanings

It can also be a [fragment spec resolver](#fragment-spec-resolver) or a [operation mock resolver](#operation-mock-resolver).

## Response

The data returned by a GraphQL server in response to a query, mutation, or subscription. A GraphQL response typically contains a `data` field with the requested information, and may also include an `errors` field if any errors occurred during execution.

In Relay, responses are processed by the [Response Normalizer](#response-normalizer), which transforms the nested response data into a flat, normalized format suitable for storage in the Relay store. This normalization process enables efficient data deduplication, caching, and updates.

Responses can also include extensions and other metadata depending on the GraphQL server implementation. Relay handles both successful responses and error responses, providing appropriate error handling and data consistency guarantees.

## Response Normalizer

A class, exposing a single method `normalize`. This will traverse the denormalized response from the API request, normalize it and write the normalized results into a given `MutableRecordSource`. It is called from the query executor.

## Restore

TODO

## Retain

TODO

## Render Policy

The "Render Policy" in Relay determines how data is rendered in components, specifically whether to use "full" or "partial" rendering. This policy integrates with React's Suspense to manage when components should suspend based on data availability.
* Full Rendering: This approach waits until all required data is available before rendering a component. It ensures that components do not render with incomplete data, which can prevent flickering or unexpected UI changes.
* Partial Rendering: This approach allows components to render with the data that is currently available, even if some data is missing. It can improve perceived performance by displaying parts of the UI sooner, but may lead to components rendering with null or incomplete data.

The choice between full and partial rendering can be configured per environment or query, allowing developers to optimize for specific use cases.
<FbInternalOnly>
For example, Comet defaults to partial rendering to accommodate certain product behaviors, while other environments may use full rendering to ensure data consistency.
</FbInternalOnly>

## Revert

TODO

## Root Field

A root field is a top-level field on a GraphQL root type — Query, Mutation, or Subscription. These fields serve as entry points for GraphQL operations, allowing clients to fetch, modify, or subscribe to data.


## Root Type

The [GraphQL spec](https://spec.graphql.org/June2018/#sec-Root-Operation-Types) defines three special root types: Query, Mutation and Subscription. Queries must select fields off of the Query root type, etc.

## Root

Outermost React Component for a given page or screen. Can be associated with an entrypoint.

Roots for entrypoints are referred to by the [`JSResource`](#JSResource) to the root React component module.

## Scalar

A scalar in GraphQL is a primitive, indivisible leaf value that cannot have subfields. Scalars represent basic data types, such as numbers, strings, booleans, and identifiers, which are returned directly to the client without further selection or nesting.

GraphQL defines several built-in scalar types:
* Int: A signed 32‐bit integer
* Float: A signed double-precision floating-point value
* String: A UTF‐8 character sequence
* Boolean: true or false
* ID: A unique identifier, often serialized as a string

In addition to these built-in types, GraphQL servers may define custom scalars for values like dates, times, or other domain-specific primitive types.

Relay represents GraphQL scalars as corresponding primitive JavaScript values (such as numbers, booleans, and strings). For custom scalars, Relay treats them as opaque values, providing support for their representation and use, but does not interpret their content.

For more details, see:
* [The GraphQL Specification on Scalars](https://spec.graphql.org/October2021/#sec-Scalars)
* [Relay Return Types Guide](../guides/relay-resolvers/return-types/#scalar-types)


## Scheduler

TODO

## Schema

A collection of all of the GraphQL types that are known to Relay, for a given [project](#project).

<FbInternalOnly>

## Schema Sync

The GraphQL [schema](#schema) is derived from annotations on Hack classes in the www repository.

Periodically, those changes are synced to fbsource in a schema sync diff. If the updated schema would break Relay on fbsource, these schema sync diffs will not land.

If a field is removed from www, but is only used in fbsource, the application developer may not notice that the field cannot be removed. This is a common source of schema breakages.

For more info, look [here](https://www.internalfb.com/intern/wiki/GraphQL/Build_Infra/Schema_Sync/) and [here](https://www.internalfb.com/intern/wiki/Relay-team/GraphQL_Schema_Sync/).
</FbInternalOnly>

## Selection

A "selection of fields" refers to the fields you are requesting on an object that you are accessing, as part of a query, mutation, subscription or fragment.

## Selector

See [normalization selector](#normalization-selector).

## @skip

A directive that is added to fields, inline fragments and fragment spreads, and allows for conditional inclusion. It is the opposite of the [`@include`](#include) directive.

## Snapshot

The results of running a reader selector against the data currently in the store. See [lookup](#lookup).

## Stale

In Relay, "stale" describes cached data in the client store that is no longer considered fresh or up-to-date. By default, Relay treats cached data as valid indefinitely unless it is explicitly marked as stale through invalidation APIs (`invalidateRecord`, `invalidateStore`) or if it exceeds the configured query cache expiration time. When data is stale, Relay triggers a network refetch on the next query evaluation to ensure the UI reflects the most current information. Components can also subscribe to invalidation events to respond immediately when data becomes stale (`useSubscribeToInvalidationState` hook). This mechanism helps maintain data consistency and timely updates after changes such as mutations.

For more details, see the [Relay Staleness of Data documentation](../guided-tour/reusing-cached-data/staleness-of-data.mdx).

## Store

The Relay Store is a local cache in the Relay runtime that manages the lifecycle of records fetched from a GraphQL server, as well as client-side data. It normalizes and de-dupes data, supports subscriptions and [optimistic updates](#optimistic-update), and handles garbage collection and data retention to ensure efficient data access and consistency.

In addition to server-fetched data, the Relay Store can manage client-side data, including data from resolvers and local state. Client-side resolvers compute derived data based on existing records, allowing components to access both server and client data seamlessly. The store also supports the integration of local state by adding client-specific fields to the GraphQL schema, enabling developers to query and manage local state using Relay.

## @stream

A directive which can be added to a field of `List` type that enables the individual items in the list to be delivered incrementally. The client can render the initial
set of items while waiting for the server to deliver the rest of the items. For more detail refer to GraphQL's [documentation on the @stream directive](https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.mdx#stream).

## @stream_connection

A directive that is like the @connection directive for pagination, except modified to enable items in the pagination queue to be delivered incrementally. It has the additional parameter `initial_count` to specify how many items to deliver in the initial payload. To learn more about how to use this directive refer to the [Streaming Pagination page](https://relay.dev/docs/guided-tour/list-data/streaming-pagination/).

## Subscribe

A method exposed by the Relay store. Accepts a callback and a snapshot (see [lookup](#lookup)). The Relay store will call this callback when [`notify`](#notify) is called, if the data referenced by that snapshot has been updated or invalidated.

## Subscription

[GraphQL Subscriptions](../guided-tour/updating-data/graphql-subscriptions) are a mechanism which allow clients to subscribe to changes in a piece of data from the server, and get notified whenever that data changes.

A GraphQL Subscription looks very similar to a query, with the exception that it uses the subscription keyword:

```graphql
subscription FeedbackLikeSubscription($input: FeedbackLikeSubscribeData!) {
  feedback_like_subscribe(data: $input) {
    feedback {
      id
      like_count
    }
  }
}
```

<FbInternalOnly>

See also [the guide](../guides/writing-subscriptions).

</FbInternalOnly>

## Transaction ID

A unique id for a given instance of a call to `network.execute`. This ID will be consistent for the entire duration of a network request. It can be consumed by custom log functions passed to `RelayModernEnvironment`.

## Traversal

There are four tree traversals that are core to understanding the internal behavior of Relay.

* Using the normalization AST:
  * When Relay normalizes the payload it receives from the GraphQL server in the Response Normalizer;
  * When Relay determines whether there is enough data for to fulfill an operation, in the Data Checker; and
  * When Relay determines what data is no longer accessible during garbage collection, in the [Reference Marker](#reference-marker).
* Using the reader AST:
  * When Relay reads data for rendering, in the Reader.

## Type

The GraphQL type of a field is a description of a field on a schema, in terms of what subfields it has, or what its representation is (String, number, etc.).

See also [interface](#interface-graphql), [abstract type](#abstract-type) and [the GraphQL docs](https://graphql.org/learn/schema/#type-language) for more info.

## Type Refinement

The inclusion of a fragment of particular type in a location only known to potentially implement that type. This allows us to select fields if and only if they are defined on that particular object, and return null otherwise.

For example, `node(id: 4) { ... on User { name } }`. In this case, we do not know ahead of time whether `node(id: 4)` is a User. If it is, this fragment will include the user name.

See also [abstract type refinement](#abstract-type-refinement).

## Updater

A callback passed to `commitMutation`, which provides the application developer with imperative control over the data in the store.

See [the documentation](../guided-tour/updating-data/introduction.mdx) and also [optimistic updater](#optimistic-updater).

## Value

A single value on a record, such as `has_viewer_liked`, or `name`.

Compare with [linked record](#linked-record).

## Variables

GraphQL variables are a construct that allows referencing dynamic values inside a GraphQL query. They must be provided when the query is initiated, and can be used throughout nested fragments.

See the [variables section of the guided tour](../guided-tour/rendering/variables) and compare with [@argumentDefinitions](#argumentdefinitions).

<DocsRating />

---

### Guides Alias Directive (`website/docs/guides/alias-directive.mdx`)

---
id: alias-directive
title: "@alias Directive"
slug: /guides/alias-directive/
description: Relay guide to @alias
keywords:
- alias
- directive
- fragment
---

The `@alias` directive allows you to expose a spread fragment — either a named fragment spread or an inline fragment — as a named field within your selection. This allows Relay to provide additional type safety in the case where your fragment’s type may not match the parent selection.

:::info
This document describes why the `@alias` directive was introduced, and how it can be used to improve type safety in your Relay applications. **To learn about its API, see the [API Reference](../api-reference/graphql/graphql-directives.mdx#alias).**
:::

Let's look at an example where `@alias` can be useful:

## Abstract Types

Imagine you have a component that renders information about a Viewer:

```ts
function MyViewer({viewerKey}) {
  const {name} = useFragment(graphql`
    fragment MyViewer on Viewer {
      name @required(action: THROW)
    }`, viewerKey);

  return `My name is ${name}. That's ${name.length} letters long!`;
}
```

To use that component in a component that has a fragment on Node (which Viewer implements), you could write something like this:

```ts
function MyNode({nodeKey}) {
  const node = useFragment(graphql`
    fragment MyFragment on Node {
      ...MyViewer
    }`, nodeKey);

  return <MyViewer viewerKey={node} />
}
```

Can you spot the problem? We don’t actually know that the node we are passing to `<MyViewer />` is actually a Viewer `<MyViewer />`. If `<MyNode />` tries to render a Comment — which also implements Node — we will get a runtime error in `<MyViewer />` because the field name is not present on Comment.

```
TypeError: Cannot read properties of undefined (reading 'length')
```

Not only do we not get a type letting us know that about this potential issue, but even at runtime, there is no way to check if node implements Viewer because Viewer is an abstract type!

## Aliased Fragments

Aliased fragments can solve this problem. Here’s what `<MyNode />` would look like using them:

```ts
function MyNode({nodeKey}) {
  const node = useFragment(graphql`
    fragment MyFragment on Node {
      ...MyViewer @alias(as: "my_viewer")
    }`, nodeKey);

  // Relay returns the fragment key as its own nullable property
  if(node.my_viewer == null) {
    return null;
  }

  // Because `my_viewer` is typed as nullable, Flow/TypeScript will
  // show an error if you try to use the `my_viewer` without first
  // performing a null check.
  //                          VVVVVVVVVVVVVV
  return <MyViewer viewerKey={node.my_viewer} />
}
```

With this approach, you can see that Relay exposes the fragment key as its own nullable property, which allows us to check that node actually implements Viewer and even allows Flow to enforce that the component handles the possibility!

## @skip and @include

A similar problem can occur when using `@skip` and `@include` directives on fragments. In order to safely use the spread fragment, you need to check if it was fetched. Historically this has required gaining access to the query variable that was used to determine if the fragment was skipped or included.

With `@alias`, you can now check if the fragment was fetched by simply assigning the fragment an alias, and checking if the alias is null:

```ts
function MyUser({userKey}) {
  const user = useFragment(graphql`
    fragment MyFragment on User {
      ...ConditionalData @skip(if: $someVar) @alias
    }`, userKey);

  if(user.ConditionalData == null) {
    return "No data fetched";
  }
  return <ConditionalData userKey={user.ConditionalData} />
}
```

## Enforced Safety

We've outlined two different ways that fragments can be unsafe in Relay today without `@alias`. To help prevent runtime issues resulting from these unsafe edge cases, Relay requires that all conditionally fetched fragments are aliased.

To disable this validation in your project, you can disable the `enforce_fragment_alias_where_ambiguous` compiler feature flag for your project. If you need to enable incremental adoption of this enforcement, Relay exposes a directive `@dangerously_unaliased_fixme` which will suppress enforcement errors. This will allow you to enable the enforcement for all new spreads without first needing to migrate all existing issues.

The [Relay VSCode extension](../editor-support.mdx) offers quick fixes to add either `@alias` or `@dangerously_unaliased_fixme` to unsafe fragments, and the
[mark-dangerous-conditional-fragment-spreads](../codemods/#mark-dangerous-conditional-fragment-spreads) codemod can be used to apply `@dangerously_unaliased_fixme` across your entire project.

## Use with @required

`@alias` can be used with [`@required(action: NONE)`](./required-directive.mdx) to group together required fields. In the following example, we group `name` and `email` together as `requiredFields`. If either is null, that null will bubble up to, the `user.requiredFields` field, making it null. This allows us to perform a single check, without impacting the `id` field.

```ts
function MyUser({userKey}) {
  const user = useFragment(graphql`
    fragment MyFragment on User {
      id
      ... @alias(as: "requiredFields") {
        name @required(action: NONE)
        email @required(action: NONE)
      }
    }`, userKey);

  if(user.requiredFields == null) {
    return `Missing required fields for user ${user.id}`;
  }
  return `Hello ${user.requiredFields.name} (${user.requiredFields.email}).!`;
}
```

:::note
Using `@required` on a fragment spread that has an `@alias` is not currently supported, but we may add support in the future.
:::

## Under the Hood

For people familiar with Relay, or curious to learn, here is a brief description of how this feature is implemented:

Under the hood, `@alias` is implemented entirely within Relay (compiler and runtime). It does not require any server support. The Relay compiler interprets the `@alias` directive, and generates types indicating that the fragment key, or inline fragment data, will be attached to the new field, rather than directly on the parent object. In the Relay runtime artifact, it wraps the fragment node with a new node indicating the name of the alias and additional information about the type of the fragment.

The Relay compiler also inserts an additional field into the spread which allows it to determine if the fragment has matched:

```graphql
fragment Foo on Node {
  ... on Viewer {
    isViewer: __typename # <-- Relay inserts this
    name
  }
}
```

Relay can now check for the existence of the `isViewer` field in the response to know if the fragment matched.

When Relay reads the content of your fragment out of the store using its runtime artifact, it uses this information to attach the fragment key to this new field, rather than attaching it directly to the parent object.

### Related

While `@alias` is a Relay-specific feature, it draws inspiration from fragment modularity as outlined in the GraphQL [RFC Fragment Modularity](https://github.com/graphql/graphql-wg/blob/main/rfcs/FragmentModularity.mdx).

---

### Guides Catch Directive (`website/docs/guides/catch-directive.mdx`)

---
id: catch-directive
title: '@catch Directive'
slug: /guides/catch-directive/
description: Relay guide to @catch
keywords:
  - catch
  - directive
  - optional
---

import DocsRating from '@site/src/core/DocsRating';

The `@catch` directive can be added to fields, fragment/operation definitions or
aliased inline fragment spreads declare how exceptions and unexpected values
should be handled at runtime. Using `@catch` allows Relay to surface these error
states as part of your fragment/query/mutation data instead of a null value
(which has been the default behavior), or a runtime exception if
[`@throwOnFieldError`](./throw-on-field-error-directive.mdx) is being used.

:::tip
Both `@catch` and `@throwOnFieldError` only handle field errors in the
query/fragment/mutation in which they are used. They **do not** handle errors
related to fields in any spread fragments.
:::

## `to` Argument

The `@catch` directive accepts an optional `to` argument which has two options:

- `RESULT` (default): The value is returned as `{ ok: true, value: T } | { ok: false, errors: [error] }`. This allows you implement explicit field-granular error handling in your application.
- `NULL`: If an error is encountered within the `@catch`, the value will be replaced with `null`.

## Examples

If a `@catch` error is caught directly on the field that the error originated
from - the error is provided on that field. Here's an example:

```graphql
query MyQuery {
  viewer {
    name @catch
    age
  }
}
```

If `name` contains an error - it would be provided in the response data on the
`name` field - like so:

```js
{
  viewer: {
    name: {
      ok: false,
      errors: [{path: ['viewer', 'name']}]
    }
    age: 39
  }
}
```

However, if `@catch` exists on one of the ancestors of a field, that error will
bubble up to there, like so:

```graphql
query MyQuery {
  viewer @catch {
    name
    age
  }
}
```

```js
{
  viewer: {
    ok: false,
    errors: [{ path: ['viewer', 'name'] } ]
  }
}
```

## Implications for nullability

Fields whose errors are explicitly handled by `@catch`, either by being
annotated with `@catch` or by being nested with a `@catch` ancestor will be
typed using their [Semantic Nullability](./semantic-nullability.mdx). In other
words, if a field has been marked as `@semanticNonNull` in the server schema to
indicate that it will only be null in the case of error, Relay will type that
field as non-nullable in its generated Flow/TypeScript types.

## What can be caught with `@catch`?

### Payload Field Errors

Payload [field
errors](https://spec.graphql.org/October2021/#sec-Errors.Field-errors) are
errors that occur as the result of a server-side exception while executing a
given field's resolver. In this case, the GraphQL specifies that the server must
provide a null value where a value should be, and a separate errors object.

When you `@catch` on a field, Relay takes those errors and provides them to you
in-line instead, making them easier to handle, and no longer invisible.

### @required(action: THROW) within an @catch

If you have an `@required(action: THROW)` with an ancestor that contains a
`@catch` - instead of throwing an exception, the `@required` error would bubble
up and be provided in the same way normal errors would. Here's an example:

```graphql
query MyQuery {
  viewer @catch {
    name @required(action: THROW)
    age
  }
}
```

```js
{
  viewer: {
    ok: false,
    errors: [{ path: ["viewer", "name"] }]
  }
}
```

### Missing Data in response

[Here is an example of where missing data may occur in Relay](https://relay.dev/docs/next/debugging/why-null/#graph-relationship-change)

If a field is expected to have a value, and that field is undefined - the field
is considered to be "missing data". This is also an unexpected state - and when
it happens with an `@catch` as an ancestor, it will also be caught like so:

```js
{
  viewer: {
    ok: false,
    errors: [{ path: ["viewer", "name"] }]
  }
}
```

## How does `@catch` interact with `@throwOnFieldError`?

Using `@throwOnFieldError` enables fields to throw a JavaScript exception when a
field error occurs. By using `@catch` - you tell Relay that you don't want a
JavaScript exception in this case. Instead, you are requesting that the error be
provided in the data object, with the same behaviors and rules as are listed
above (including bubbling to a parent field).

It is important to note that you can still use @catch without
@throwOnFieldError. It will still provide you the error in the data object. But
other fields that are not under a `@catch` will still not throw - because
`@throwOnFieldError` would be missing.

Read more about `@throwOnFieldError`
[here](https://relay.dev/docs/next/api-reference/graphql-and-directives/#throwonfielderror-experimental).

## GraphQL Conf Talk

The Relay team gave a talk at GraphQL Conf 2024 about `@catch` and explicit error handling in Relay. You can watch it here:

<iframe src="https://www.youtube-nocookie.com/embed/_TSYKAtaK5A" width={640} height={360} allowFullScreen={true} frameBorder="0" />

---

### Guides Client Schema Extensions (`website/docs/guides/client-schema-extensions.mdx`)

---
id: client-schema-extensions
title: Client Schema Extensions
slug: /guides/client-schema-extensions/
description: Relay guide to client schema extensions
keywords:
- client
- schema
- extension
- commitLocalUpdate
---

import DocsRating from '@site/src/core/DocsRating';

:::note
See also [the local data updates](../../guided-tour/updating-data/local-data-updates/) and [client-only data](../../guided-tour/updating-data/client-only-data/) sections of the guided tour.
:::

Relay can be used to read and write local data, and act as a single source of truth for _all_ data in your client application.

The Relay Compiler fully supports client-side extensions of the schema, which allows you to define local fields and types.

## Table of Contents:

-   [Extending the server schema](#extending-the-server-schema)
-   [Querying local state](#querying-local-state)
-   [Mutating local state](#mutating-local-state)
-   [Initial local state](#initial-local-state)

## Extending the server schema

To extend the server schema, create a new `.graphql` file inside your `--src`
directory.  Let's call it `./src/clientSchema.graphql`.  This file needs to be
referenced in the `"schemaExtensions"` of your Relay config, either directly or
via its folder.

This schema describes what local data can be queried on the client.
It can even be used to extend an existing server schema.

For example, we can create a new type called `Note`:

```graphql
type Note {
  id: ID!
  title: String
  body: String
}
```

And then extend the server schema type `User`, with a list of `Note`, called `notes`.

```graphql
extend type User {
  notes: [Note]
}
```

## Querying local state

Accessing local data is no different from querying your GraphQL server, although you are required to include at least one server field in the query.
The field can be from the server schema, or it can be schema agnostic, like an introspection field (e.g. `__typename`).

Here, we use [useLazyLoadQuery](../../api-reference/use-lazy-load-query) to get the current `User` via the `viewer` field, along with their id, name and the local list of notes.

```javascript
// Example.js
import * as React from 'react';
import { useLazyLoadQuery, graphql } from 'react-relay';

const Example = (props) => {
  const data = useLazyLoadQuery(graphql`
    query ExampleQuery {
      viewer {
        id
        name
        notes {
          id
          title
          body
        }
      }
    }
  `, {});
  // ...
}
```

## Mutating local state

All local data lives in the [Relay Store](../../api-reference/store/).

Updating local state can be done with any `updater` function.

The `commitLocalUpdate` function is especially ideal for this, because writes to local state are usually executed outside of a mutation.

To build upon the previous example, let's try creating, updating and deleting a `Note` from the list of `notes` on `User`.

### Create

```javascript
import {commitLocalUpdate} from 'react-relay';

let tempID = 0;

function createUserNote(environment) {
  commitLocalUpdate(environment, store => {
    const user = store.getRoot().getLinkedRecord('viewer');
    const userNoteRecords = user.getLinkedRecords('notes') || [];

    // Create a unique ID.
    const dataID = `client:Note:${tempID++}`;

    //Create a new note record.
    const newNoteRecord = store.create(dataID, 'Note');

    // Add the record to the user's list of notes.
    user.setLinkedRecords([...userNoteRecords, newNoteRecord], 'notes');
  });
}
```

Note that since this record will be rendered by the `ExampleQuery` via `useLazyLoadQuery`, the query data will automatically be retained and won't be garbage collected.

If no component is rendering the local data and you want to manually retain it, you can do so by calling `environment.retain()`:

```javascript
import {createOperationDescriptor, getRequest} from 'relay-runtime';

// Create a query that references that record
const localDataQuery = graphql`
  query LocalDataQuery {
    viewer {
      notes {
        __typename
      }
    }
  }
`;

// Create an operation descriptor for the query
const request = getRequest(localDataQuery);
const operation = createOperationDescriptor(request, {} /* variables */);


// Tell Relay to retain this operation so any data referenced by it isn't garbage collected
// In this case, all the notes linked to the `viewer` will be retained
const disposable = environment.retain(operation);


// Whenever you don't need that data anymore and it's okay for Relay to garbage collect it,
// you can dispose of the retain
disposable.dispose();
```

### Update

```javascript
import {commitLocalUpdate} from 'react-relay';

function updateUserNote(environment, dataID, body, title) {
  commitLocalUpdate(environment, store => {
    const note = store.get(dataID);

    note.setValue(body, 'body');
    note.setValue(title, 'title')
  });
}
```

### Delete

```javascript
import {commitLocalUpdate} from 'react-relay';

function deleteUserNote(environment, dataID) {
  commitLocalUpdate(environment, store => {
    const user = store.getRoot().getLinkedRecord('viewer');
    const userNoteRecords = user.getLinkedRecords('notes');

    // Remove the note from the list of user notes.
    const newUserNoteRecords = userNoteRecords.filter(x => x.getDataID() !== dataID);

    // Delete the note from the store.
    store.delete(dataID);

    // Set the new list of notes.
    user.setLinkedRecords(newUserNoteRecords, 'notes');
  });
}
```

## Initial local state

All new client-side schema fields default to `undefined` value. Often however, you will want to set the initial state before querying local data.
You can use an updater function via `commitLocalUpdate` to prime local state.

```javascript
import {commitLocalUpdate} from 'react-relay';

commitLocalUpdate(environment, store => {
  const user = store.getRoot().getLinkedRecord('viewer');

  // initialize user notes to an empty array.
  user.setLinkedRecords([], 'notes');
});
```

<DocsRating />

---

### Guides Codemods (`website/docs/guides/codemods.mdx`)

---
id: codemods
title: Codemods
slug: /guides/codemods/
description: Relay guide to codemods
keywords:
  - codemod
  - codemods
---

import DocsRating from '@site/src/core/DocsRating'; import {FbInternalOnly,
OssOnly, fbContent} from 'docusaurus-plugin-internaldocs-fb/internal'; import
Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';

The Relay compiler has the ability to make changes across the source files of
your projects with the use of codemods. You can see the list of codemods
available by running the Relay compiler's `codemod` command:

```
> relay codemod --help
Apply codemod (verification with auto-applied fixes)

Usage: relay codemod [OPTIONS] [CONFIG] <COMMAND>

Commands:
  mark-dangerous-conditional-fragment-spreads  Marks unaliased conditional fragment spreads as @dangerously_unaliased_fixme
  remove-unnecessary-required-directives       Removes @required directives from non-null fields within @throwOnFieldError fragments and operations.
  fix-all                                      Runs all Relay compiler transforms and fixes all fixable diagnostics
  help                                         Print this message or the help of the given subcommand(s)

Arguments:
  [CONFIG]  Compile using this config file. If not provided, searches for a config in package.json under the `relay` key or `relay.config.json` files among other up from the current working directory

Options:
  -p, --project <project>  Compile only this project. You can pass this argument multiple times. to compile multiple projects. If excluded, all projects will be compiled
  -h, --help               Print help
```

## Available codemods

The compiler currently has these available codemods:

### mark-dangerous-conditional-fragment-spreads

This codemod finds fragment spreads that are _dangerously unaliased_; that is,
the fragment might not be fetched due to a directive such as `@skip` or its
inclusion on a mismatched type within a union. If such a conditional fragment is
not aliased with [`@alias`](../alias-directive/), there is no way for the
resulting generated Flow or TypeScript types to reflect its nullability. This
codemod will add the `@dangerously_unaliased_fixme` directive to such fragment
spreads, indicating to developers that there is a problem to be fixed. After
applying this codemod, the `enforce_fragment_alias_where_ambiguous` feature flag
can be enabled, which will ensure any future ambiguous fragment spreads must be
aliased.

Since this codemod can potentially modify many files, there is an optional
`--rollout-percentage` parameter (shorthand: `-r`) which, if used alongside the
`enforce_fragment_alias_where_ambiguous` feature flag in rollout mode, allows
progressive codemod and enforcement of this validation.

### remove-unnecessary-required-directives

Removes [@required](../api-reference/graphql/graphql-directives.mdx#required)
directives from non-null fields within
[@throwOnFieldError](../api-reference/graphql/graphql-directives.mdx#throwonfielderror)
fragments and operations, or linked fields with
[`@catch`](../guides/catch-directive.mdx), where the compiler is certain that the
directive does not change the generated types for the data being fetched.

### fix-all

Runs all Relay compiler transforms and automatically applies fixes for every
fixable diagnostic. This is a convenient catch-all codemod to apply when
upgrading Relay versions — run it after updating the package to repair any
issues the compiler now flags:

```sh
relay codemod fix-all
```

---

### Guides Document Comparison (`website/docs/guides/document-comparison.mdx`)

---
id: document-comparison
title: Document Comparison
slug: /guides/document-comparison/
description: Relay guide to document comparison
keywords:
  - compare
  - diff
  - ir
---

import DocsRating from '@site/src/core/DocsRating';

:::note
This feature is **experimental** and the API may change in future versions.
:::

The Relay compiler includes an experimental feature for comparing the intermediate representations (IR) of two GraphQL documents. This feature determines whether one document is a subset of another and reports any missing selections.

This feature is particularly useful for comparing documents generated by LLMs where exact match of LLM generated documents and static expected documents is neither attainable or desirable, due to the nature of LLMs. In those cases, you could:
* Specify (via `--left`) an expected document with minimally required selections, and determine if the LLM generated document (via `--right`) contains all required selections, via the subset test that the command performs.
* Optionally, pass exepected document via `--right` and LLM generated document via `--left` to determine whether LLM generated documents contains extra selections than expected, aka. overfetching.

## Usage

```
> relay experimental-compare-document-ir --help
EXPERIMENTAL! Compare intermediate representations (IR) of documents passed via left and right, outputs selections that exists in left but not in right.

Usage: relay experimental-compare-document-ir [OPTIONS] --left <LEFT> --right <RIGHT>

Options:
      --left <LEFT>                    Document in string, must contain exactly 1 operation
      --right <RIGHT>                  Document in string, must contain exactly 1 operation
      --schemaPaths <SCHEMA_PATHS>...  Path(s) to the full schema file(s) to convert documents to intermediate representation (IR) for comparison
  -h, --help                           Print help
```

## Output

Detailed information about missing selection(s) from the right document, including line number and path.

## How It Works

The 2 documents (left and right) are first transformed to their Intermediate Representation (IR), then to **Normalized Tree** form, for comparison. Each node of the tree corresponds to a selection in the original document, and is checked for its existence in the other tree.

### Normalized Trees

Each IR is transformed into a normalized tree structure that:
- **Inlines fragments**: Fragment spreads and inline fragments are inlined, while type conditions specified by the fragment are encoded in the node.
- **De-aliases fields**: Converts aliased fields to their original names (e.g., `my_id: id` → `id`)
- **Deduplicates fields**: Removes duplicate identical fields
- **Tracks type conditions**: Records which concrete object types can reach each scalar field at the leaf level

The normalized tree mirrors the JSON response structure of the query.

#### Tree Node Identity
Consists of
- Path from operation root to the corresponding selection
- Field arguments of the corresponding selection (if applicable)
- Type condition: the type that the enclosing object must be, for the corresponding selection to be included in the response. E.g. with `... on A { id }`, the type condition of selection `id` is `A` if `A` is a concrete type, or a set of types that are `A` if `A` is an abstract type.

#### Tree Node Existence

A selection exists in a tree if:
- An identical selection is found
- A superset of the selection is found. A selection is a superset of another if:
  - It allows the same selection and more, with query variables. E.g. `user(id: $id)` is a superset of `user(id: 100)` because variable `$id` can be set to arbitrary values, including `100`, at runtime.
  - Its type condition is a superset of another.

## Example

**Left document:**
```graphql
query A {
  viewer {
    timezone_estimate {
      display_name
      gmt_offset
    }
  }
}
```

**Right document:**
```graphql
query A {
  viewer {
    timezone_estimate {
      display_name
    }
  }
}
```

**Output**
```text
[INFO] Found 1 missing selection(s):
    4 │       display_name
    5 │       gmt_offset
      │       ^^^^^^^^^^
    6 │     }
* query -> viewer -> timezone_estimate -> gmt_offset
```

Explore [tests](https://github.com/facebook/relay/blob/main/compiler/crates/graphql-ir-diff/tests/ir_diff_test.rs) for more examples.

---

### Guides Graphql Server Specification (`website/docs/guides/graphql-server-specification.mdx`)

---
id: graphql-server-specification
title: GraphQL Server Specification
slug: /guides/graphql-server-specification/
description: Relay GraphQL server specification guide
keywords:
- GraphQL
- server
- specification
---

import DocsRating from '@site/src/core/DocsRating';

The goal of this document is to specify the assumptions that Relay makes about a GraphQL server and demonstrate them through an example GraphQL schema.

Table of Contents:

-   [Preface](#preface)
-   [Schema](#schema)
-   [Object Identification](#object-identification)
-   [Connections](#connections)
-   [Further Reading](#further-reading)

## Preface

The two core assumptions that Relay makes about a GraphQL server are that it provides:

1.  A mechanism for refetching an object.
2.  A description of how to page through connections.

This example demonstrates all two of these assumptions. This example is not comprehensive, but it is designed to quickly introduce these core assumptions, to provide some context before diving into the more detailed specification of the library.

The premise of the example is that we want to use GraphQL to query for information about ships and factions in the original Star Wars trilogy.

It is assumed that the reader is already familiar with [GraphQL](http://graphql.org/); if not, the README for [GraphQL.js](https://github.com/graphql/graphql-js) is a good place to start.

It is also assumed that the reader is already familiar with [Star Wars](https://en.wikipedia.org/wiki/Star_Wars); if not, the 1977 version of Star Wars is a good place to start, though the 1997 Special Edition will serve for the purposes of this document.

## Schema

The schema described below will be used to demonstrate the functionality that a GraphQL server used by Relay should implement. The two core types are a faction and a ship in the Star Wars universe, where a faction has many ships associated with it.

```graphql
interface Node {
  id: ID!
}

type Faction implements Node {
  id: ID!
  name: String
  ships: ShipConnection
}

type Ship implements Node {
  id: ID!
  name: String
}

type ShipConnection {
  edges: [ShipEdge]
  pageInfo: PageInfo!
}

type ShipEdge {
  cursor: String!
  node: Ship
}

type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  startCursor: String
  endCursor: String
}

type Query {
  rebels: Faction
  empire: Faction
  node(id: ID!): Node
}
```

## Object Identification

Both `Faction` and `Ship` have identifiers that we can use to refetch them. We expose this capability to Relay through the `Node` interface and the `node` field on the root query type.

The `Node` interface contains a single field, `id`, which is an `ID!`. The `node` root field takes a single argument, an `ID!`, and returns a `Node`. These two work in concert to allow refetching; if we pass the `id` returned in that field to the `node` field, we get the object back.

Let's see this in action, and query for the ID of the rebels:

```graphql
query RebelsQuery {
  rebels {
    id
    name
  }
}
```

returns

```json
{
  "rebels": {
    "id": "RmFjdGlvbjox",
    "name": "Alliance to Restore the Republic"
  }
}
```

So now we know the ID of the Rebels in our system. We can now refetch them:

```graphql
query RebelsRefetchQuery {
  node(id: "RmFjdGlvbjox") {
    id
    ... on Faction {
      name
    }
  }
}
```

returns

```json
{
  "node": {
    "id": "RmFjdGlvbjox",
    "name": "Alliance to Restore the Republic"
  }
}
```

If we do the same thing with the Empire, we'll find that it returns a different ID, and we can refetch it as well:

```graphql
query EmpireQuery {
  empire {
    id
    name
  }
}
```

yields

```json
{
  "empire": {
    "id": "RmFjdGlvbjoy",
    "name": "Galactic Empire"
  }
}
```

and

```graphql
query EmpireRefetchQuery {
  node(id: "RmFjdGlvbjoy") {
    id
    ... on Faction {
      name
    }
  }
}
```

yields

```json
{
  "node": {
    "id": "RmFjdGlvbjoy",
    "name": "Galactic Empire"
  }
}
```

The `Node` interface and `node` field assume globally unique IDs for this refetching. A system without globally unique IDs can usually synthesize them by combining the type with the type-specific ID, which is what was done in this example.

The IDs we got back were base64 strings. IDs are designed to be opaque (the only thing that should be passed to the `id` argument on `node` is the unaltered result of querying `id` on some object in the system), and base64ing a string is a useful convention in GraphQL to remind viewers that the string is an opaque identifier.

Complete details on how the server should behave are available in the [GraphQL Object Identification](https://graphql.org/learn/global-object-identification/) best practices guide in the GraphQL site.

## Connections

A faction has many ships in the Star Wars universe. Relay contains functionality to make manipulating one-to-many relationships easy, using a standardized way of expressing these one-to-many relationships. This standard connection model offers ways of slicing and paginating through the connection.

Let's take the rebels, and ask for their first ship:

```graphql
query RebelsShipsQuery {
  rebels {
    name
    ships(first: 1) {
      edges {
        node {
          name
        }
      }
    }
  }
}
```

yields

```json
{
  "rebels": {
    "name": "Alliance to Restore the Republic",
    "ships": {
      "edges": [
        {
          "node": {
            "name": "X-Wing"
          }
        }
      ]
    }
  }
}
```

That used the `first` argument to `ships` to slice the result set down to the first one. But what if we wanted to paginate through it? On each edge, a cursor will be exposed that we can use to paginate. Let's ask for the first two this time, and get the cursor as well:

```
query MoreRebelShipsQuery {
  rebels {
    name
    ships(first: 2) {
      edges {
        cursor
        node {
          name
        }
      }
    }
  }
}
```

and we get back

```json

{
  "rebels": {
    "name": "Alliance to Restore the Republic",
    "ships": {
      "edges": [
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjA=",
          "node": {
            "name": "X-Wing"
          }
        },
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjE=",
          "node": {
            "name": "Y-Wing"
          }
        }
      ]
    }
  }
}
```

Notice that the cursor is a base64 string. That's the pattern from earlier: the server is reminding us that this is an opaque string. We can pass this string back to the server as the `after` argument to the `ships` field, which will let us ask for the next three ships after the last one in the previous result:

```

query EndOfRebelShipsQuery {
  rebels {
    name
    ships(first: 3 after: "YXJyYXljb25uZWN0aW9uOjE=") {
      edges {
        cursor
        node {
          name
        }
      }
    }
  }
}
```

gives us

```json


{
  "rebels": {
    "name": "Alliance to Restore the Republic",
    "ships": {
      "edges": [
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjI=",
          "node": {
            "name": "A-Wing"
          }
        },
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjM=",
          "node": {
            "name": "Millennium Falcon"
          }
        },
        {
          "cursor": "YXJyYXljb25uZWN0aW9uOjQ=",
          "node": {
            "name": "Home One"
          }
        }
      ]
    }
  }
}
```

Sweet! Let's keep going and get the next four!

```graphql
query RebelsQuery {
  rebels {
    name
    ships(first: 4 after: "YXJyYXljb25uZWN0aW9uOjQ=") {
      edges {
        cursor
        node {
          name
        }
      }
    }
  }
}
```

yields

```json
{
  "rebels": {
    "name": "Alliance to Restore the Republic",
    "ships": {
      "edges": []
    }
  }
}
```

Hm. There were no more ships; guess there were only five in the system for the rebels. It would have been nice to know that we'd reached the end of the connection, without having to do another round trip in order to verify that. The connection model exposes this capability with a type called `PageInfo`. So let's issue the two queries that got us ships again, but this time ask for `hasNextPage`:

```graphql
query EndOfRebelShipsQuery {
  rebels {
    name
    originalShips: ships(first: 2) {
      edges {
        node {
          name
        }
      }
      pageInfo {
        hasNextPage
      }
    }
    moreShips: ships(first: 3 after: "YXJyYXljb25uZWN0aW9uOjE=") {
      edges {
        node {
          name
        }
      }
      pageInfo {
        hasNextPage
      }
    }
  }
}
```

and we get back

```json
{
  "rebels": {
    "name": "Alliance to Restore the Republic",
    "originalShips": {
      "edges": [
        {
          "node": {
            "name": "X-Wing"
          }
        },
        {
          "node": {
            "name": "Y-Wing"
          }
        }
      ],
      "pageInfo": {
        "hasNextPage": true
      }
    },
    "moreShips": {
      "edges": [
        {
          "node": {
            "name": "A-Wing"
          }
        },
        {
          "node": {
            "name": "Millennium Falcon"
          }
        },
        {
          "node": {
            "name": "Home One"
          }
        }
      ],
      "pageInfo": {
        "hasNextPage": false
      }
    }
  }
}
```

So on the first query for ships, GraphQL told us there was a next page, but on the next one, it told us we'd reached the end of the connection.

Relay uses all of this functionality to build out abstractions around connections, to make these easy to work with efficiently without having to manually manage cursors on the client.

Complete details on how the server should behave are available in the [GraphQL Cursor Connections](https://relay.dev/graphql/connections.htm) spec.

## GraphQL Conf Talk

Sabrina Wasserman, an engineer at Meta, gave a talk at GraphQL Conf 2024 deriving the GraphQL connection spec, and explaining how having the behavior of list pagination specified can enable powerful tooling for clients broadly, not just Relay.

<iframe src="https://www.youtube-nocookie.com/embed/PGBC-0E-kco" width={640} height={360} allowFullScreen={true} frameBorder="0" />

## Further Reading

This concludes the overview of the GraphQL Server Specifications. For the detailed requirements of a Relay-compliant GraphQL server, a more formal description of the [Relay cursor connection](https://relay.dev/graphql/connections.htm) model, the [GraphQL global object identification](https://graphql.org/learn/global-object-identification/) model are all available.

To see code implementing the specification, the [GraphQL.js Relay library](https://github.com/graphql/graphql-relay-js) provides helper functions for creating nodes and connections; that repository's [`__tests__`](https://github.com/graphql/graphql-relay-js/tree/main/src/__tests__) folder contains an implementation of the above example as integration tests for the repository.

<DocsRating />

---

### Guides Network Layer (`website/docs/guides/network-layer.mdx`)

---
id: network-layer
title: Network Layer
slug: /guides/network-layer/
description: Relay guide to the network layer
keywords:
- network
- caching
---

import DocsRating from '@site/src/core/DocsRating';

In order to know how to access your GraphQL server, Relay requires developers to provide an object implementing the `INetwork` interface when creating an instance of a [Relay Environment](../api-reference/relay-runtime/relay-environment.mdx). The environment uses this network layer to execute queries, mutations, and (if your server supports them) subscriptions. This allows developers to use whatever transport (HTTP, WebSockets, etc) and authentication is most appropriate for their application, decoupling the environment from the particulars of each application's network configuration.

Currently the easiest way to create a network layer is via a helper from the `relay-runtime` package:

```javascript
import {
  Environment,
  Network,
  RecordSource,
  Store,
} from 'relay-runtime';

// Define a function that fetches the results of an operation (query/mutation/etc)
// and returns its results as a Promise:
function fetchQuery(
  operation,
  variables,
  cacheConfig,
  uploadables,
) {
  return fetch('/graphql', {
    method: 'POST',
    headers: {
      // Add authentication and other headers here
      'content-type': 'application/json'
    },
    body: JSON.stringify({
      query: operation.text, // GraphQL text from input
      variables,
    }),
  }).then(response => {
    return response.json();
  });
}

// Create a network layer from the fetch function
const network = Network.create(fetchQuery);
const store = new Store(new RecordSource())

const environment = new Environment({
  network,
  store
  // ... other options
});

export default environment;
```

:::warning
This is just a basic example to help you get started. Features like `@stream`, `@defer` or Persisted Queries will require additional logic be added to your `fetchQuery` function.
:::

## Advanced Network Layer

The network layer provides a place for developers to customize the data fetching behaviors. For example, adding network level caching, telemetry or support for uploading form data for mutations.

<DocsRating />

---

### Guides Persisted Queries (`website/docs/guides/persisted-queries.mdx`)

---
id: persisted-queries
title: Persisted Queries
slug: /guides/persisted-queries/
description: Relay guide to persisted queries
keywords:
- persisted
---

import DocsRating from '@site/src/core/DocsRating';
import {FbInternalOnly, OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

<FbInternalOnly>

:::tip
At Meta, persistence is handled by the `relay` command for you. You likely do not need to worry about the contents of this guide.
:::

</FbInternalOnly>

The Relay compiler supports persisted queries. This is useful because:

-   The client operation text becomes just an md5 hash which is usually shorter than the real
    query string. This saves upload bytes from the client to the server.

-   The server can now allowlist queries which improves security by restricting the operations
    that can be executed by a client.

<OssOnly>

## Usage on the client

### The `persistConfig` option

In the `relay` configuration section of your `package.json` you'll need specify
"persistConfig".

```
"scripts": {
  "relay": "relay-compiler",
  "relay-persisting": "node relayLocalPersisting.js"
},
"relay": {
  "src": "./src",
  "schema": "./schema.graphql",
  "persistConfig": {
    "url": "http://localhost:2999",
    "params": {}
  }
}
```

Specifying `persistConfig` in the config will do the following:

1.  It converts all query and mutation operation texts to md5 hashes.

    For example without `persistConfig`, a generated `ConcreteRequest` might look
    like below:

    ```javascript
    const node/*: ConcreteRequest*/ = (function(){
    //... excluded for brevity
    return {
      "kind": "Request",
      "operationKind": "query",
      "name": "TodoItemRefetchQuery",
      "id": null, // NOTE: id is null
      "text": "query TodoItemRefetchQuery(\n  $itemID: ID!\n) {\n  node(id: $itemID) {\n    ...TodoItem_item_2FOrhs\n  }\n}\n\nfragment TodoItem_item_2FOrhs on Todo {\n    text\n    isComplete\n}\n",
      //... excluded for brevity
    };
    })();

    ```

    With `persistConfig` this becomes:

    ```javascript
    const node/*: ConcreteRequest*/ = (function(){
    //... excluded for brevity
    return {
      "kind": "Request",
      "operationKind": "query",
      "name": "TodoItemRefetchQuery",
      "id": "3be4abb81fa595e25eb725b2c6a87508", // NOTE: id is now an md5 hash
      // of the query text
      "text": null, // NOTE: text is null now
      //... excluded for brevity
    };
    })();

    ```

2.  It will send an HTTP POST request with a `text` parameter to the
specified `url`.
You can also add additional request body parameters via the `params` option.

```
"scripts": {
  "relay": "relay-compiler"
},
"relay": {
  "src": "./src",
  "schema": "./schema.graphql",
  "persistConfig": {
    "url": "http://localhost:2999",
    "params": {}
  }
}
```

### Local Persisted Queries

With the following config, you can generate a local JSON file which contains a map of `operation_id => full operation text`.

```
"scripts": {
  "relay": "relay-compiler"
},
"relay": {
  "src": "./src",
  "schema": "./schema.graphql",
  "persistConfig": {
    "file": "./persisted_queries.json",
    "algorithm": "MD5" // this can be one of MD5, SHA256, SHA1
  }
}
```

Ideally, you'll take this file and ship it to your server at deploy time so your server knows about all the queries it could possibly receive. If you don't want to do that, you'll have to implement the [Automatic Persisted Queries handshake](https://www.apollographql.com/docs/apollo-server/performance/apq/).

#### Tradeoffs

- ✅ If your server's persisted query datastore gets wiped, you can recover automatically through your client's requests.
- ❌ When there's a cache miss, it'll cost you an extra round trip to the server.
- ❌ You'll have to ship your `persisted_queries.json` file to the browser which will increase your bundle size.

### Example implementation of `relayLocalPersisting.js`

Here's an example of a simple persist server that will save query text to the `queryMap.json` file.


```
/* Detailed source-code truncated for AI context efficiency. */
```

The example above writes the complete query map file to `./queryMap.json`.
To use this, you'll need to update `package.json`:


```
"scripts": {
  "persist-server": "node ./relayLocalPersisting.js",
  "relay": "relay-compiler"
}
```

</OssOnly>

### Network layer changes

You'll need to modify your network layer fetch implementation to pass an ID parameter in the POST body (e.g., `doc_id`) instead of a query parameter:

```javascript
function fetchQuery(operation, variables) {
  return fetch('/graphql', {
    method: 'POST',
    headers: {
      'content-type': 'application/json'
    },
    body: JSON.stringify({
      doc_id: operation.id, // NOTE: pass md5 hash to the server
      // query: operation.text, // this is now obsolete because text is null
      variables,
    }),
  }).then(response => {
    return response.json();
  });
}
```


## Executing Persisted Queries on the Server

<FbInternalOnly>

Your server should then look up the query referenced by `doc_id` when responding to this request.

</FbInternalOnly>

<OssOnly>

To execute client requests that send persisted queries instead of query text, your server will need to be able
to lookup the query text corresponding to each ID. Typically this will involve saving the output of the `queryMap.json` JSON file to a database or some other storage mechanism, and retrieving the corresponding text for the ID specified by a client.

Additionally, your implementation of `relayLocalPersisting.js` could directly save queries to the database or other storage.

For universal applications where the client and server code are in one project, this is not an issue since you can place
the query map file in a common location accessible to both the client and the server.

### Compile time push

For applications where the client and server projects are separate, one option is to have an additional npm run script
to push the query map at compile time to a location accessible by your server:

```javascript
"scripts": {
  "push-queries": "node ./pushQueries.js",
  "persist-server": "node ./relayLocalPersisting.js",
  "relay": "relay-compiler && npm run push-queries"
}
```

Some possibilities of what you can do in `./pushQueries.js`:

-   `git push` to your server repo.

-   Save the query maps to a database.

### Run time push

A second more complex option is to push your query maps to the server at runtime, without the server knowing the query IDs at the start.
The client optimistically sends a query ID to the server, which does not have the query map. The server then in turn requests
for the full query text from the client so it can cache the query map for subsequent requests. This is a more complex approach
requiring the client and server to interact to exchange the query maps.

### Simple server example

Once your server has access to the query map, you can perform the mapping. The solution varies depending on the server and
database technologies you use, so we'll just cover the most common and basic example here.

If you use `express-graphql` and have access to the query map file, you can import it directly and
perform the matching using the `persistedQueries` middleware from [express-graphql-persisted-queries](https://github.com/kyarik/express-graphql-persisted-queries).

```javascript
import express from 'express';
import {graphqlHTTP} from 'express-graphql';
import {persistedQueries} from 'express-graphql-persisted-queries';
import queryMap from './path/to/queryMap.json';

const app = express();

app.use(
  '/graphql',
  persistedQueries({
    queryMap,
    queryIdKey: 'doc_id',
  }),
  graphqlHTTP({schema}),
);
```

## Using `persistConfig` and `--watch`

It is possible to continuously generate the query map files by using the `persistConfig` and `--watch` options simultaneously.
This only makes sense for universal applications i.e. if your client and server code are in a single project
and you run them both together on localhost during development. Furthermore, in order for the server to pick up changes
to the `queryMap.json`, you'll need to have server side hot-reloading set up. The details on how to set this up
are out of the scope of this document.

</OssOnly>

<DocsRating />

---

### Guides Required Directive (`website/docs/guides/required-directive.mdx`)

---
id: required-directive
title: "@required Directive"
slug: /guides/required-directive/
description: Relay guide to @required
keywords:
- required
- directive
- optional
- nullthrows
---

import DocsRating from '@site/src/core/DocsRating';

The `@required` directive can be added to fields in your Relay queries to declare how null values should be handled at runtime. You can think of it as saying "if this field is ever null, its parent field is invalid and should be null".

When you have a GraphQL schema where many fields are nullable, a considerable amount of product code is needed to handle each field's potential "nullness" before the underlying data can be used. With `@required`, Relay can handle some types of null checks before it returns data to your component, which means that **any field you annotate with** **`@required`** **will become non-nullable in the generated types for your response**.

If a `@required` field is null at runtime, Relay will "bubble" that nullness up to the field's parent. For example, given this query:

```graphql
query MyQuery {
  viewer {
    name @required(action: LOG)
    age
  }
}
```

If `name` is null, Relay would return `{ viewer: null }`. You can think of `@required` in this instance as saying "`viewer` is useless without a `name`".

## Action

The `@required` directive has a required `action` argument which has four possible values:

### `NONE` (expected)

This field is expected to be null sometimes. The field's nullability will "bubble up" to make the parent field null if this field is missing, allowing the component to check the parent field instead of this specific field.

### `LOG` (recoverable)

This value is not expected to ever be null, but the component **can still render** if it is. If a field with `action: LOG` is null, the [Relay field logger](../api-reference/relay-runtime/field-logger.mdx) will receive a `missing_required_field.log` event. The field's nullability will "bubble up" to make the parent field null.

### `THROW` (unrecoverable)

This value should not be null, and the component **cannot render without it**. If a field with `action: THROW` is null at runtime, the component which reads that field **will throw during render**. The error message includes both the owner and field path. Only use this option if your component is contained within an [error boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary).

**Note**: If you have opted into the optional `disallow_required_action_throw_on_semantically_nullable_fields` [compiler feature flag](../../docs/getting-started/compiler-config.mdx), this can only be used on fields that are non-nullable (`!` in the schema) or are marked with `@semanticNonNull` (an optional [semantic nullability](./semantic-nullability.mdx) feature that indicates fields should never be null in normal operation).

### `DANGEROUSLY_THROW_ON_SEMANTICALLY_NULLABLE_FIELD` (unrecoverable, bypass validation)

:::warning
This option is included mostly as a migration path for existing codebases that used `@required(action: THROW)` on nullable fields. It is strongly discouraged to add new usages of this option.
:::

This action behaves identically to `THROW` but can be used on nullable fields. This is only needed when the optional [compiler feature flag](https://relay.dev/docs/getting-started/compiler-config/#FeatureFlags) `disallow_required_action_throw_on_semantically_nullable_fields` is enabled, which prevents using THROW on semantically nullable fields.


## Locality

A field's `@required` status is **local to the fragment where it is specified**. This allows you to add/remove the directive without having to think about anything outside the scope of your component.

This choice reflects the fact that some components may be able to recover better from missing data than others. For example, a `<RestaurantInfo />` component could probably render something sensible even if the restaurant's address is missing, but a `<RestaurantLocationMap />` component might not.

However, all usages of the `@required` directive on the same field in a single fragment must be consistent with their usage. This situation mostly occurs when selecting fields in inline fragments. For example, the following fragment would fail to compile:

```graphql
fragment UserInfo on User {
  job {
    ... on Actor {
      certifications
    }
    ... on Lawyer {
      certifications @required(action: LOG)
    }
  }
}
```

The Relay compiler will give you an error like `All references to a field must have matching @required declarations.`. To fix this, either set the `@required` directive on each of the fields selected in the inline fragment or remove the directive entirely.

## Chaining

`@required` directives can be chained to make a deeply nested field accessible after just one null check:

```javascript
const user = useFragment(graphql`
  fragment MyUser on User {
    name @required(action: LOG)
    profile_picture @required(action: LOG) {
      url @required(action: LOG)
    }
  }`, key);
 if(user == null) {
   return null;
 }
 return <img src={user.profile_picture.url} alt={user.name} />
```

**Note**: If you use `@required` on a top level field of a fragment, the object returned from `useFragment` itself may become nullable. The generated types will reflect this.

When chaining `@required` directives, the Relay compiler will help you from unintentionally creating a chain with a more severe action than intended. Consider the following fragment

```graphql
fragment MyUser on User {
  profile_picture @required(action: THROW) {
    url @required(action: LOG)
  }
}
```

In this example we want the component to THROW if the `profile_picture` field is null but we only want to LOG an error if the `url` field is null. But recall, Relay will "bubble" nullness up to the parent field, if the `url` field is null it will then cause the `profile_picture` field to become null as well. And once that happens, the component will THROW. If you implement a pattern like this, the Relay compiler will give you an error

```
A @required field may not have an `action` less severe than that of its @required parent. This @required directive should probably have `action: LOG` so that it can match its parent
```

To fix this, either change the `profile_picture` to use `action: LOG` or change the `url` field to use `action: THROW`.

## Caveats with Connections

There are currently some limitations in using the `@required` and `@connection` directives together. When you use the `@connection` directive, Relay  automatically inserts some additional fields into the connection, and those fields won't be generated with the `@required` directive. This can result in inconsistencies if you use the `@required` directive on fields in a Connection type. Consider the following example:

```graphql
fragment FriendsList on User @refetchable(queryName: "FriendsListQuery") {
  friends(after: $cursor, first: $count) @connection(key: "FriendsList_friends") {
    edges {
      node @required(action: LOG) {
        job @required(action: LOG) {
          title @required(action: LOG)
        }
      }
    }
  }
}
```

Any usages of `@required` on the `node` field or any of its direct child fields will cause the Relay compiler to give you an error saying `All references to a field must have matching @required declarations.`. In order to bypass this you'll need to remove the `@required` directives on those fields.

In the above example, we'd need to remove the `@required` directives on both the `node` and `job` fields, but the usage on the `title` field would not create an error.

```graphql
fragment FriendsList on User @refetchable(queryName: "FriendsListQuery") {
  friends(after: $cursor, first: $count) @connection(key: "FriendsList_friends") {
    edges {
      node {
        job {
          title @required(action: LOG)
        }
      }
    }
  }
}
```

## FAQ

### Why did @required make a non-nullable field/root nullable?

When using the `LOG` or `NONE` actions, Relay will "bubble" a missing field up to its parent field or fragment root. This means that adding `@required(action: LOG)` (for example) to a child of a non-nullable fragment root will cause the type of the fragment root to become nullable.

### What happens if you use `@required` in a plural field

If a `@required(action: LOG)` field is missing in a plural field, the _item_ in the list will be returned as null. It will _not_ cause the entire array to become null.. If you have any question about how it will behave, you can inspect the generated Flow types.

### Why are @required fields in an inline fragment still nullable?

Imagine a fragment like this:

```graphql
fragment MyFrag on Actor {
  ... on User {
    name @required(action: THROW)
  }
}
```

It's possible that your `Actor` will not be a `User` and therefore not include a `name`. To represent that in types, we generate a Flow type that looks like this: `{name?: string}`.

If you encounter this issue, you can add a `__typename` like this:

```graphql
fragment MyFrag on Actor {
  __typename
  ... on User {
    name @required(action: THROW)
  }
}
```

In this situation Relay will generate a union type like: `{__typename: 'User', name: string} | {__typename: '%ignore this%}`. Now you can check the `__typename` field to narrow your object's type down to one that has a non-nullable `name`.

### Why not implement this at the schema/server level?

The "requiredness" of a field is actually a product decision and not a schema question. Therefore we need to implement the handling of it at the product level. Individual components need to be able to decide for themselves how to handle a missing value.

For example, if a notification is trying to show the price for a Marketplace listing, it could probably just omit the price and still render. If payment flow for that same listing is missing the price, it should probably blow up.

Another issue is that changes to the server schema are much more difficult to ship since they affect all existing clients across all platforms.

Basically every value returned by Relay is nullable. This is intentional since we want to be able to handle field-level errors whenever possible. If we lean into KillsParentOnException we would end up wanting to make basically every field use it and our apps would be becomes more brittle since errors which used to be small, become large.

<FbInternalOnly>

_Extracted from [this comment thread](https://fb.workplace.com/groups/cometeng/permalink/937671436726844/?comment_id=937681186725869)._
_Further discussion in [this comment thread](https://fb.workplace.com/groups/cometeng/permalink/937671436726844/?comment_id=938335873327067)._

</FbInternalOnly>

### Can `(action: NONE)` be the default?

On one hand action: NONE makes the most sense as a default (omitted action == no action). However, we are aware that whichever value we choose as the default will be considered the default action for engineers to choose since it's the path of least resistance.

We actually believe that in most cases LOG is the most ideal choice. It gives the component a chance to gracefully recover while also giving us signal that a part of our app is rendering in a sub-optimal way.

We debated making LOG the default action for that reason, but I think that's confusing as well.

So, for now we are planning to not offer a default argument. After all, it's still much less to write out than the equivalent manual null checks. Once we see how people use it we will consider what value (if any) should be the default.

---

### Guides Semantic Nullability (`website/docs/guides/semantic-nullability.mdx`)

---
id: semantic-nullability
title: "Semantic Nullability"
slug: /guides/semantic-nullability/
description: Experimental support for semantic nullability
keywords:
- "null"
- nullability
- semanticNonNull
---

## Motivation

One of GraphQL's strengths is its field-granular error handling which can dramatically improve response resiliency. However, today that error handling depends upon field nullability, which is the reason it is a [recommended best practice](https://graphql.org/learn/best-practices/#nullability) to default all fields to being nullable. This creates a trade-off where __enabling maximum resiliency means client developers must manually handle all possible permutations of field nullability__ within their components. [`@required`](./required-directive.mdx) can help a bit, but is ultimately a very blunt tool.

## Proposed Solution

[Semantic Nullability](https://github.com/graphql/graphql.github.io/blob/nullability-post/src/pages/blog/2024-08-14-exploring-true-nullability.mdx#our-latest-proposal) is an early GraphQL spec proposal that aims to decouple error handling and nullability in the GraphQL spec to enable maximum resiliency while still exposing the "semantic nullability", (the nullability of the actual resolver function/method on the server) of the field to the client.

The proposal works by allowing the schema to specify a new type of nullability of "null only on error". If a client sees this type, _and_ the client has some strategy for handling field errors out-of-band, it may treat the field that is exposed to user code as non-nullable.

The full spec change will likely require adding additional syntax to GraphQL's schema definition language, but in the meantime, various GraphQL servers and clients have collaborated on a temporary directive [`@semanticNonNull`](https://specs.apollo.dev/nullability/v0.2/) that can be used to experiment with this idea.

In short, you can add `@semanticNonNull` to a field in your schema to indicate that the field is non-nullable in the semantic sense, but that the client should still be prepared to handle errors.

Relay will look for `@semanticNonNull` directives in your schema and generate non-nullable Flow/TypeScript types for those fields if you enable client-side error handling for your query or fragment by adding the [`@throwOnFieldError`](./throw-on-field-error-directive.mdx) directive.

If your server will never return `null` for a user's name, except in the case of errors, for example because it's resolver is typed as non-nullable, you can then apply `@semanticNonNull` to that field in your schema.

```graphql title="schema.graphql"
directive @semanticNonNull(levels: [Int] = [0]) on FIELD_DEFINITION

type User {
  name: String @semanticNonNull
}
```

Once you've added the directive to your schema, you can add `@throwOnFieldError` to your fragment and queries to indicate that the client should throw an error if any field errors are encountered when the fragment is read.

:::note
Be sure to add [React error boundaries](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) to your app above any components that are using `@throwOnFieldError`.
:::

In the below example, Relay's generated TypeScript or Flow types for `user.name` will be non-nullable.

:::caution
If Relay receives a field error for `user.name`, `useFragment` will throw an error. For this reason, it's important to ensure that you are have adequate [React error boundaries](../guided-tour/rendering/error-states.mdx) in place to catch these errors.
:::

```js
import type {UserComponent_user$key} from 'UserComponent_user.graphql';

const React = require('React');
const {graphql, useFragment} = require('react-relay');

type Props = {
  user: UserComponent_user$key,
};

function UserComponent(props: Props) {
  const user = useFragment(
    graphql`
      fragment UserComponent_user on User @throwOnFieldError {
        name # Will be typed as non-nullable
      }
    `,
    props.user,
  );

  return <div>{user.name}</div>
}
```

## By Example

For a hands on example, see [this example project](https://github.com/captbaritone/grats-relay-example/pull/1) showing Relay configured to use `@semanticNonNull` and `@throwOnFieldError` alongside [Grats](https://grats.capt.dev/) which [has support](https://grats.capt.dev/docs/guides/strict-semantic-nullability/) for automatically deriving a schema that includes the experimental `@semanticNonNull` directives.

## GraphQL Conf Talk

The Relay team gave a talk at GraphQL Conf 2024 about semantic nullability. You can watch it here:

<iframe src="https://www.youtube-nocookie.com/embed/kVYlplb1gKk" width={640} height={360} allowFullScreen={true} frameBorder="0" />


## Further Reading

- [True Nullability Schema](https://github.com/graphql/graphql-wg/discussions/1394)
- [Strict Semantic Nullability](https://github.com/graphql/graphql-wg/discussions/1410)
- [RFC: SemanticNonNull type (null only on error)](https://github.com/graphql/graphql-spec/pull/1065)
- [Grat's support/documentation for `@SemanticNonNull`](https://grats.capt.dev/docs/guides/strict-semantic-nullability/)
- [Apollo's specification for this directive](https://specs.apollo.dev/nullability/v0.2/)
- [Support for `@SemanticNonNull` in Apollo Kotlin](https://www.apollographql.com/docs/kotlin/v4/advanced/nullability/#handle-semantic-non-null-with-semanticnonnull) added in [4.0.0-beta.3](https://github.com/apollographql/apollo-kotlin/releases/tag/v4.0.0-beta.3)
- [Awesome Semantic Nullability](https://github.com/captbaritone/awesome-semantic-nullability) a list of frameworks and stand alone tools that support semantic nullability

---

### Guides Testing Relay Components (`website/docs/guides/testing-relay-components.mdx`)

---
id: testing-relay-components
title: Testing Relay Components
slug: /guides/testing-relay-components/
description: Relay guide to testing Relay components
keywords:
- testing
- createMockEnvironment
- RelayMockEnvironment
- MockPayloadGenerator
- relay_test_operation
- queuePendingOperation
- resolver
---

import DocsRating from '@site/src/core/DocsRating';
import {FbInternalOnly, OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## Abstract

The purpose of this document is to cover the Relay APIs for testing Relay components.

The content is focused mostly on jest unit-tests (testing individual components) and integration tests (testing a combination of components).  But these testing tools may be applied in different cases: screenshot-tests, production smoke-tests, "Redbox" tests, fuzz-tests, e2e test, etc.

What are the benefits of writing jest tests:

* In general, it improves the stability of the system. Flow helps with catching a various set of Javascript errors, but it is still possible to introduce regressions to the components. Unit-tests help find, reproduce, and fix regressions, and prevent them in the future.
* It simplifies the refactoring process: when properly written (testing public interface, not implementation) - tests help with changing the internal implementation of the components.
* It may speed up and improve the development workflow. Some people may call it Test Driven Development (TM). But essentially it's just writing tests for public interfaces of your components, and then writing the components that implement those interfaces. Jest —watch mode really shines in this case.
* It will simplify the on-boarding process for new developers. Having tests helps new developers ramp up on the new code base, allowing them to fix bugs and deliver features.

One thing to notice: while jest unit- and integration tests will help improve the stability of the system, they should be considered one part of a bigger stability infrastructure with multiple layers of automated testing: flow, e2e, screenshot, "Redbox", performance tests.

## Testing with Relay

Testing applications that use Relay may be challenging, because of the additional data fetching layer that wraps the actual product code.

And it's not always easy to understand the mechanics of all processes that are happening behind Relay, and how to properly handle interactions with the framework.

Fortunately, there are tools that aim to simplify the process of writing tests for Relay components, by providing imperative APIs for controlling the request/response flow and additional API for mock data generation.

There are two main Relay modules that you may use in your tests:

* `createMockEnvironment(options): RelayMockEnvironment`
* `MockPayloadGenerator` and the `@relay_test_operation` directive

With `createMockEnvironment,` you will be able to create an instance of `RelayMockEnvironment`, a Relay environment specifically for your tests. The instance created by `createMockEnvironment` implements the Relay Environment Interface and it also has an additional Mock layer, with methods that allow you to resolve/reject and control the flow of operations (queries/mutations/subscriptions).

The main purpose of `MockPayloadGenerator` is to improve the process of creating and maintaining the mock data for tested components.

One of the patterns you may see in the tests for Relay components: 95% of the test code is the test preparation—the gigantic mock object with dummy data, manually created, or just a copy of a sample server response that needs to be passed as the network response. And the remaining 5% is actual test code. As a result, people don't test much. It's hard to create and manage all these dummy payloads for different cases. Hence, writing tests is time-consuming and tests are sometimes painful to maintain.

With the `MockPayloadGenerator` and `@relay_test_operation`, we want to get rid of this pattern and switch the developer's focus from the preparation of the test to the actual testing.

## Testing with React and Relay

**[React Testing Library](https://testing-library.com/react)** is a set of helpers that let you test React components without relying on their implementation details. This approach makes refactoring a breeze and also nudges you towards best practices for accessibility. Although it doesn't provide a way to "shallowly" render a component without its children, a test runner like Jest lets you do this by [mocking](https://reactjs.org/docs/testing-recipes.html#mocking-modules).

<FbInternalOnly>

Note: The [`ReactTestRenderer`](https://www.npmjs.com/package/react-test-renderer) library has been deprecated since React v18. `ReactTestRenderer` may still be referenced internally as an alternative to React Testing Library. However, when possible, we recommend using React Testing Library (or `@testing-library/react-native`) to test your React applications with Relay.

</FbInternalOnly>

## RelayMockEnvironment API Overview

RelayMockEnvironment is a special version of Relay Environment with additional API methods for controlling the operation flow: resolving and rejection operations, providing incremental payloads for subscriptions, working with the cache.

* Methods for finding operations executed on the environment
    * `getAllOperations()` - get all operation executed during the test by the current time
    * `findOperation(findFn => boolean) `- find particular operation in the list of all executed operations, this method will throw, if operation is not available. Maybe useful to find a particular operation when multiple operations executed at the same time
    * `getMostRecentOperation() -` return the most recent operation, this method will throw if no operations were executed prior this call.
* Methods for resolving or rejecting operations
    * `nextValue(request | operation, data)` - provide payload for operation(request), but not complete request. Practically useful when testing incremental updates and subscriptions
    * `complete(request | operation)`  - complete the operation, no more payloads are expected for this operation, when it's completed.
    * `resolve(request | operation, data)` - resolve the request with provided GraphQL response. Essentially, it's nextValue(...) and complete(...)
    * `reject(request | operation, error)` - reject the request with particular error
    * `resolveMostRecentOperation(operation => data)` - resolve and getMostRecentOperation work together
    * `rejectMostRecentOperation(operation => error)`  - reject and getMostRecentOperation work together
    * `queueOperationResolver(operation => data | error)` - adds an OperationResolver function to the queue. The passed resolver will be used to resolve/reject operations as they appear
    * `queuePendingOperation(query, variables)` - in order for the `usePreloadedQuery` hook to not suspend, one must call these functions:
        * `queueOperationResolver(resolver)`
        * `queuePendingOperation(query, variables)`
        * `preloadQuery(mockEnvironment, query, variables)` with the same `query` and `variables` that were passed to `queuePendingOperation`. `preloadQuery` must be called after `queuePendingOperation`.
* Additional utility methods
    * `isLoading(request | operation)` - will return `true` if operations has not been completed, yet.
    * `cachePayload(request | operation, variables, payload)` - will add payload to QueryResponse cache
    * `clearCache() `- will clear QueryResponse cache

## Mock Payload Generator and the `@relay_test_operation` Directive

`MockPayloadGenerator` may drastically simplify the process of creating and maintaining mock data for your tests. `MockPayloadGenerator` can generate dummy data for the selection that you have in your operation. There is an API to modify the generated data - Mock Resolvers. With Mock Resolvers, you may adjust the data for your needs. Mock Resolvers are defined as an object where **keys are names of GraphQL types (`ID`, `String`, `User`, `Comment`, etc),** and values are functions that return the default data for the type.

Example of a simple Mock Resolver:

```js
{
  ID() {
    // Return mock value for a scalar filed with type ID
    return 'my-id';
  },
  String() {
    // Every scalar field with type String will have this default value
    return "Lorem Ipsum"
  }
}
```


It is possible to define more resolvers for Object types

```js
{
  // This will be the default values for User object in the query response
  User() {
    return {
      id: 4,
      name: "Mark",
      profile_picture: {
        uri: "http://my-image...",
      },
    };
  },
}
```



### Mock Resolver Context

The first argument of the MockResolver is the object that contains Mock Resolver Context. It is possible to return dynamic values from mock resolvers based on the context - for instance, name or alias of the field, a path in the selection, arguments, or parent type.


```js
{
  String(context) {
    if (context.name === 'zip') {
      return '94025';
    }
    if (context.path != null && context.path.join('.') === 'node.actor.name') {
      return 'Current Actor Name';
    }
    if (context.parentType === 'Image' && context.name === 'uri') {
       return 'http://my-image.url';
    }
  }
}
```

### ID Generation

The second argument of the Mock Resolver is a function that will generate a sequence of integers, useful to generate unique ids in the tests

```js
{
  // will generate strings "my-id-1", "my-id-2", etc.
  ID(_, generateId) {
     return `my-id-${generateId()}`;
  },
}
```

### Float, Integer, Boolean, etc...

Please note, that for production queries we don't have full type information for Scalar fields - like Boolean, Integer, Float. And in the MockResolvers, they map to String. You can use `context` to adjust return values, based on the field name, alias, etc.

### @relay_test_operation

Most of GraphQL type information for a specific field in the selection is not available during Relay runtime. By default, Relay, cannot get type information for a scalar field in the selection, or an interface type of the object.

Operation with the @relay_test_operation directive will have additional metadata that will contain GraphQL type info for fields in the operation's selection. And it will improve the quality of the generated data. You also will be able to define Mock resolvers for Scalar (not only ID and String) and Abstract types:

```javascript
{
  Float() {
    return 123.456;
  },
  Boolean(context) {
    if (context.name === 'can_edit') {
      return true;
    }
    return false;
  },
  Node() {
    return {
      __typename: 'User',
      id: 'my-user-id',
    };
  }
}
```

## Examples

### Relay Component Test

Using `createMockEnvironment` and `MockPayloadGenerator` allows writing concise tests for components that use Relay hooks. Both those modules can be imported from `relay-test-utils`


```
/* Detailed source-code truncated for AI context efficiency. */
```

#### Component Tests With Deferred Fragments

When using `MockPayloadGenerator` to generate data for a Query that has fragments with `@defer` you may want to generate the deferred data as well. To do so, you can use `MockPayloadGenerator.generateWithDefer` passing the option `generateDeferredPayload`:

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Fragment Component Tests

Essentially, in the example above, `resolveMostRecentOperation` will generate data for all child fragment containers (pagination, refetch). But, usually the root component may have many child fragment components and you may want to exercise a specific component that uses `useFragment`. The solution for that would be to wrap your fragment container with the `useLazyLoadQuery` component that renders a Query that spreads fragments from your fragment component:

```javascript
test('Fragment', () => {
  const environment = createMockEnvironment();
  const TestRenderer = () => {
    const data = useLazyLoadQuery(
      graphql`
        query TestQuery @relay_test_operation {
          myData: node(id: "test-id") {
            # Spread the fragment you want to test here
            ...MyFragment
          }
        }
      `,
      {},
    );
    return <MyFragmentComponent myData={data.myData} />
  };

  const renderer = render(
    <RelayEnvironmentProvider environment={environment}>
      <Suspense fallback="Loading...">
        <TestRenderer />
      </Suspense>
    </RelayEnvironmentProvider>
  );

  // Wrapping in act will ensure that components
  // are fully updated to their final state.
  act(() => {
    environment.mock.resolveMostRecentOperation(operation =>
      MockPayloadGenerator.generate(operation),
    );
  });

  expect(renderer).toMatchSnapshot();
});
```

### Pagination Component Test

Essentially, tests for pagination components (e.g. using `usePaginationFragment`) are not different from fragment component tests. But we can do more here, we can actually see how the pagination works - we can assert the behavior of our components when performing pagination (load more, refetch).

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Refetch Component

We can use similar approach here with wrapping the component with a query. And for the sake of completeness, we will add an example here:

```js
test('Refetch Container', async () => {
  const environment = createMockEnvironment();
  const TestRenderer = () => {
    const data = useLazyLoadQuery(
      graphql`
        query TestQuery @relay_test_operation {
          myData: node(id: "test-id") {
            # Spread the pagination fragment you want to test here
            ...MyRefetchableFragment
          }
        }
      `,
      {},
    );
    return <MyRefetchContainer data={data.myData} />
  };

  const renderer = render(
    <RelayEnvironmentProvider environment={environment}>
      <Suspense fallback="Loading...">
        <TestRenderer />
      </Suspense>
    </RelayEnvironmentProvider>
  );

  act(() => {
    environment.mock.resolveMostRecentOperation(operation =>
      MockPayloadGenerator.generate(operation),
    );
  });

  // Assuming we have refetch button in the Container
  const refetchButton = await renderer.findByTestId('refetch');

  // This should trigger the `refetch`
  refetchButton.props.onClick();

  act(() => {
    environment.mock.resolveMostRecentOperation(operation =>
      MockPayloadGenerator.generate(operation, {
        // We can customize mock resolvers, to change the output of the refetch query
      }),
    );
  });

  expect(renderer).toMatchSnapshot();
});
```



### Mutations

Mutations themselves are operations, so we can test them independently (unit-test) for a specific mutation, or in combination with the view from which this mutation is called.

:::note
the `useMutation` API is an improvement over calling `commitMutation` directly.
:::

```js
// Say, you have a mutation function
function sendMutation(environment, onCompleted, onError, variables)
  commitMutation(environment, {
    mutation: graphql`...`,
    onCompleted,
    onError,
    variables,
  });
}

// Example test may be written like so
test('it should send mutation', () => {
  const environment = createMockEnvironment();
  const onCompleted = jest.fn();
  sendMutation(environment, onCompleted, jest.fn(), {});
  const operation = environment.mock.getMostRecentOperation();

  act(() => {
    environment.mock.resolve(
      operation,
      MockPayloadGenerator.generate(operation)
    );
  });

  expect(onCompleted).toBeCalled();
});
```

### Subscription

:::tip
The `useSubscription` API is an improvement over calling `requestSubscription` directly.
:::

We can test subscriptions similarly to how we test mutations.

```js
// Example subscribe function
function subscribe(environment, onNext, onError, variables)
  requestSubscription(environment, {
    subscription: graphql`...`,
    onNext,
    onError,
    variables,
  });
}

// Example test may be written like so
test('it should subscribe', () => {
  const environment = createMockEnvironment();
  const onNext = jest.fn();
  subscribe(environment, onNext, jest.fn(), {});
  const operation = environment.mock.getMostRecentOperation();

  act(() => {
    environment.mock.nextValue(
      operation,
      MockPayloadGenerator.generate(operation)
    );
  });

  expect(onNext).toBeCalled();
});
```

### Example with `queueOperationResolver`

With `queueOperationResolver` it is possible to define responses for operations that will be executed on the environment

```javascript
// Say you have a component with the QueryRenderer
const MyAwesomeViewRoot = require('MyAwesomeViewRoot');
const {
  createMockEnvironment,
  MockPayloadGenerator,
} = require('relay-test-utils');

test('Data Render', async () => {
  const environment = createMockEnvironment();
  environment.mock.queueOperationResolver(operation =>
    MockPayloadGenerator.generate(operation),
  );

  const renderer = render(
    <MyAwesomeViewRoot environment={environment} />,
  );

  // At this point operation will be resolved
  // and the data for a query will be available in the store
  expect(await renderer.findByTestId('myButton')).toBeDefined();
});

test('Error State', async () => {
  const environment = createMockEnvironment();
  environment.mock.queueOperationResolver(() =>
    new Error('Uh-oh'),
  );
  const renderer = render(
    <MyAwesomeViewRoot environment={environment} />,
  );

  expect(await renderer.findByTestId('myButton')).toBeDefined();
});
```

### With Relay Hooks

The examples in this guide should work for testing components both with Relay Hooks, Containers or Renderers. When writing tests that involve the `usePreloadedQuery` hook, please also see the `queuePendingOperation` note above.

### toMatchSnapshot(...)

Even though in all of the examples here you can see assertions with `toMatchSnapshot()`, we keep it that way just to make examples concise. But it's not the recommended way to test your components.

### More Examples

<FbInternalOnly>

As a reference implementation I've put working examples here:
https://phabricator.internmc.facebook.com/diffusion/FBS/browse/master/xplat/js/RKJSModules/Libraries/Relay/oss/relay-test-utils/__tests__/RelayMockEnvironmentWithComponents-test.js

</FbInternalOnly>

<OssOnly>

The best source of example tests is in [the relay-experimental package](https://github.com/facebook/relay/tree/main/packages/relay-experimental/__tests__).

</OssOnly>

Testing is good. You should definitely do it.

<DocsRating />

---

### Guides Testing Relay With Preloaded Queries (`website/docs/guides/testing-relay-with-preloaded-queries.mdx`)

---
id: testing-relay-with-preloaded-queries
title: Testing Relay with Preloaded Queries
slug: /guides/testing-relay-with-preloaded-queries/
description: Relay guide to testing with preloaded queries
keywords:
- testing
- preloaded
- usePreloadedQuery
- queueOperationResolver
- queuePendingOperation
---

import DocsRating from '@site/src/core/DocsRating';
import {FbInternalOnly, OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

Components that use preloaded queries (`useQueryLoader` and `usePreloadedQuery` hooks) require slightly different and more convoluted test setup.

In short, there are two steps that need to be performed **before rendering the component**

1. Configure the query resolver to generate the response via `environment.mock.queueOperationResolver`
2. Record a pending queue invocation via `environment.mock.queuePendingOperation`

## Symptoms that something is wrong

1. The test doesn't do what is expected from it.
2. The query seems to be blocking instead of executing
   1. E.g. the `Suspend` doesn't switch from "waiting" to "data loaded" state
3. If you add the `console.log` before and after `usePreloadedQuery`, only the "before" call is hit

## TL;DR

```javascript
const {RelayEnvironmentProvider} = require('react-relay');
const {MockPayloadGenerator, createMockEnvironment} = require('relay-test-utils');
const {act, render} = require('@testing-library/react');
test("...", () => {
  // arrange
  const environment = createMockEnvironment();
  environment.mock.queueOperationResolver(operation => {
      return MockPayloadGenerator.generate(operation, {
        CurrencyAmount() {
          return {
            formatted_amount: "1234$",
          };
        },
      });
    });
  const query = YourComponentGraphQLQueryGoesHere; // can be the same, or just identical
  const variables = {
    // ACTUAL variables for the invocation goes here
  };
  environment.mock.queuePendingOperation(YourComponentGraphQLQuery, variables);

 // act
  const {getByTestId, ..otherStuffYouMightNeed} = render(
    <RelayEnvironmentProvider environment={environment}>
        <YourComponent data-testid="1234" {...componentPropsIfAny}/>
    </RelayEnvironmentProvider>
  );
  // trigger the loading - click a button, emit an event, etc. or ...
  act(() => jest.runAllImmediates()); // ... if loadQuery is in the useEffect()
  // assert
  // your assertions go here
});
```

### Configure the query resolver to generate the response

This is done via `environment.mock.queueOperationResolver(operation)` call, but getting it right might be tricky.

The crux of this call is to return a mocked graphql result in a very particular format (as `MockResolvers` type, to be precise). This is done via a second parameter to `generate` - it is an object, whose keys are GraphQL types that we want to mock. (See [`mock-payload-generator`](../testing-relay-components/#mock-payload-generator-and-the-relay_test_operation-directive)).

Continuing on the above example:

```js
return MockPayloadGenerator.generate(operation, {
  CurrencyAmount() { // <-- the GraphQL type
    return {
      formatted_amount: "response_value" <-- CurrencyAmount fields, selected in the query
    };
  }
});
```
The tricky thing here is to obtain the name of the GraphQL type and fields to return. This can be done in two ways:

* Call `console.log(JSON.stringify(operation, null, 2))` and look for the `concreteType` that corresponds to what we want to mock. Then look at the sibling `selections` array, which describes the fields that are selected from that object.

<FbInternalOnly>

* This is somewhat intense - P139017123 is the output for [this query](https://fburl.com/diffusion/irqurgj9). Rule of thumb - one nested call in the query produces one nested object in the output.
* Look up the type in the graphiql (bunnylol graphiql), then specify the fields listed on the query.

:::note
The type you need seems to be the type returned by the *innermost function call* (or calls, if you have multiple functions called in one query - see D23078476). This needs to be confirmed - in both example diffs the target types was also leafs.
:::

</FbInternalOnly>


It is **possible** to return different data for different query variables via [Mock Resolver Context](../testing-relay-components/#mock-resolver-context). The query variables will be available on the `context.args`, but only to the *innermost function call* (for the query above, only `offer_ids` are available)

```javascript
CurrencyAmount(context) {
  console.log(JSON.stringify(context, null, 2)); // <--
  return { formatted_amount: mockResponse }
}
// <-- logs { ...snip..., "name": "subtotal_price_for_offers", args: { offer_ids: [...] } }
```
### Record a pending queue invocation

This is more straightforward - it is done via a call to `environment.mock.queuePendingOperation(query, variables)`

* `Query` needs to match the query issues by the component. Simplest (and most robust against query changes) is to export the query from the component module and use it in the test, but having an *identical* (but not the same) query works as well.
* `variables` has to match the variables that will be used in this test invocation.
   * Beware of nested objects and arrays - they are compared via `areEqual` ([invocation code](https://github.com/facebook/relay/blob/046f758c6b411608371d4cc2f0a594ced331864e/packages/relay-test-utils/RelayModernMockEnvironment.js#L233))
      * Arrays are compared by values (not by reference), but the order of elements matter
      * Nested objects - performs deep compare, order of keys is not relevant (this is not confirmed - please update this doc if you used a graphql query with "deep" structure*)*

<FbInternalOnly>

### Example diffs

* [D23078476](https://internalfb.com/intern/diff/D23078476)
* [D23101739](https://www.internalfb.com/diff/D23101739)

</FbInternalOnly>

## Troubleshooting

* `console.log`, `console.log` everywhere! Recommended places:
   * component: before and after `useQueryLoader, usePreloadedQuery, loadQuery`
   * test: in `queueOperationResolver` callback
   * library: in `RelayModernMockEnvironment.execute`, after the `const currentOperation = ...` call ([here](https://github.com/facebook/relay/blob/046f758c6b411608371d4cc2f0a594ced331864e/packages/relay-test-utils/RelayModernMockEnvironment.js#L230))
* If `loadQuery` is not called - make sure to issue the triggering event. Depending on your component implementation it could be a user-action (like button click or key press), javascript event (via event emitter mechanisms) or a simple "delayed execution" with `useEffect`.
   * The `useEffect` case is probably easiest to miss - make sure to call `act(() => jest.runAllImmediates())` **after** rendering the component
* If "before" `usePreloadedQuery` is hit, but "after" is not - the query suspends. This entire guide is written to resolve it - you might want to re-read it. But most likely it is either:
   * Used a different query - the query resolver would not be called, `currentOperation` will be `null`
   * Query variables don't match - the query resolver would not be called, `currentOperation` will be `null` (make sure to inspect the `variables`).
      * Also, make sure arrays are in the same order, if any (or better yet, use sets, if at all possible).
* If data returned from the query is not what you expect, make sure you're generating the right graphql type.
   * You can tell you're mocking the wrong one if the return values look something like `<mock-value-for-field-"formatted_amount">`


:::note
Make sure the component and the test use the same environment (i.e. there's no `<RelayEnvironmentProvider environment={RelayFBEnvironment}>` somewhere nested in your test React tree.
:::


## Epilogue

Examples here use `testing-library-react`, but it works with the `react-test-renderer` as well.

<FbInternalOnly>

See [D23078476](https://www.internalfb.com/diff/D23078476).

</FbInternalOnly>

<DocsRating />

---

### Guides Throw On Field Error Directive (`website/docs/guides/throw-on-field-error-directive.mdx`)

---
id: throw-on-field-error-directive
title: '@throwOnFieldError Directive'
slug: /guides/throw-on-field-error-directive/
description: Relay guide to @throwOnFieldError
keywords:
  - directive
  - optional
  - errors
---

import DocsRating from '@site/src/core/DocsRating';

:::tip
Both `@catch` and `@throwOnFieldError` only handle field errors in the
query/fragment/mutation in which they are used. They **do not** handle errors
related to fields in any spread fragments.
:::

The `@throwOnFieldError` directive can be added to fragments and queries. When
this directive is used, the Relay runtime will throw an exception if a field
with a field error is encountered while reading the fragment or query, or if
Relay is missing data due to a
[graph relationship change](../debugging/why-null.mdx#graph-relationship-change).

In addition to causing the Relay runtime to throw an exception if a field error
is encountered, the `@throwOnFieldError` directive also enables generation of
non-null Flow types for fields that have the `@semanticNonNull` directive in the
schema. This means that if a field has the `@semanticNonNull` directive, the
generated Flow type for that field will be non-nullable; if an error were to
occur while reading that field, the thrown exception will prevent your
application from receiving a null value. Making a previously-nullable field
non-null may make many existing `@required` directives unnecessary; you can use
the
[remove-unnecessary-required-directives codemod](../guides/codemods.mdx#remove-unnecessary-required-directives)
to clean these up.

To use the `@throwOnFieldError` directive, add it to a fragment or query in your
Relay code. For example:

```
fragment MyFragment on User @throwOnFieldError {
  id
  name
}
```

In this example, the `@throwOnFieldError` directive is added to the MyFragment
fragment. If any of the fields in this fragment (in this case, id and name) have
a field error, the Relay runtime will throw an exception at the time the
fragment is read.

If you wish to handle a specific field error locally within your
`@throwOnFieldError` fragment or query instead of having that error throw, you
can catch the error with [@catch](./catch-directive.mdx).

**Read more about Relay's experimental support for
[Semantic Nullability](./semantic-nullability.mdx).**

---

### Guides Type Emission (`website/docs/guides/type-emission.mdx`)

---
id: type-emission
title: Type Emission
slug: /guides/type-emission/
description: Relay guide to type emission
keywords:
- type emission
---

import DocsRating from '@site/src/core/DocsRating';
import {FbInternalOnly, OssOnly, fbContent} from 'docusaurus-plugin-internaldocs-fb/internal';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

As part of its normal work, the [**Relay Compiler**](../compiler) will emit type information for your language of choice that helps you write type-safe application code. These types are included in the artifacts that `relay-compiler` generates to describe your operations and fragments.

## Operation variables

The shape of the variables object used for query, mutation, or subscription operations.

In this example the emitted type-information would require the variables object to contain an `artistID` key with a non-null string.

<Tabs
  defaultValue={fbContent({internal: 'Flow', external: 'TypeScript'})}
  values={[
    {label: 'Flow', value: 'Flow'},
    {label: 'TypeScript', value: 'TypeScript'},
  ]}>
  <TabItem value="Flow">

```javascript
/**
 * export type ExampleQuery$variables = {
 *   +artistID: string,
 * }
 * export type ExampleQuery$data = {
 *   +artist: {
 *     +name: ?string,
 *   }
 * }
 * export type ExampleQuery = {
 *   +variables: ExampleQuery$variables,
 *   +response: ExampleQuery$data,
 * }
 */

const data = useLazyLoadQuery(
  graphql`
    query ExampleQuery($artistID: ID!) {
      artist(id: $artistID) {
        name
      }
    }
  `,
  // variables are expected to be of type ExampleQuery$variables
  {artistID: 'banksy'},
);
```

  </TabItem>

  <TabItem value="TypeScript">

```javascript
/**
 * export type ExampleQuery$variables = {
 *   readonly artistID: string
 * }
 * export type ExampleQuery$data = {
 *   readonly artist?: {
 *     readonly name?: string
 *   }
 * }
 * export type ExampleQuery = {
 *   readonly variables: ExampleQuery$variables
 *   readonly response: ExampleQuery$data
 * }
 */
const data = useLazyLoadQuery(
  graphql`
    query ExampleQuery($artistID: ID!) {
      artist(id: $artistID) {
        name
      }
    }
  `,
  // variables are expected to be of type ExampleQuery$variables
  {artistID: 'banksy'},
);
```

  </TabItem>
</Tabs>

## Operation and fragment data

The shape of the data selected in a operation or fragment, following the [data-masking] rules. That is, excluding any data selected by fragment spreads.

In this example the emitted type-information describes the response data which is returned by `useLazyLoadQuery` (or `usePreloadedQuery`).

<Tabs
  defaultValue={fbContent({internal: 'Flow', external: 'TypeScript'})}
  values={[
    {label: 'Flow', value: 'Flow'},
    {label: 'TypeScript', value: 'TypeScript'},
  ]}>
  <TabItem value="Flow">

```javascript
/**
 * export type ExampleQuery$variables = {
 *   +artistID: string,
 * }
 * export type ExampleQuery$data = {
 *   +artist: {
 *     +name: ?string,
 *   }
 * }
 * export type ExampleQuery = {
 *   +variables: ExampleQuery$variables,
 *   +response: ExampleQuery$data,
 * }
 */

// data is of type ExampleQuery$data
const data = useLazyLoadQuery(
  graphql`
    query ExampleQuery($artistID: ID!) {
      artist(id: $artistID) {
        name
      }
    }
  `,
  {artistID: 'banksy'},
);

return props.artist && <div>{props.artist.name} is great!</div>
```

  </TabItem>

  <TabItem value="TypeScript">

```javascript
/**
 * export type ExampleQuery$variables = {
 *   readonly artistID: string
 * }
 * export type ExampleQuery$data = {
 *   readonly artist?: {
 *     readonly name?: string
 *   }
 * }
 * export type ExampleQuery = {
 *   readonly variables: ExampleQuery$variables
 *   readonly response: ExampleQuery$data
 * }
 */

// data is of type ExampleQuery$data
const data = useLazyLoadQuery(
  graphql`
    query ExampleQuery($artistID: ID!) {
      artist(id: $artistID) {
        name
      }
    }
  `,
  {artistID: 'banksy'},
);

return props.artist && <div>{props.artist.name} is great!</div>
```

  </TabItem>
</Tabs>


Similarly, in this example the emitted type-information describes the type of the prop to match the type of the fragment reference `useFragment` expects to receive.

<Tabs
  defaultValue={fbContent({internal: 'Flow', external: 'TypeScript'})}
  values={[
    {label: 'Flow', value: 'Flow'},
    {label: 'TypeScript', value: 'TypeScript'},
  ]}>
  <TabItem value="Flow">

```javascript
/**
 * export type ExampleFragmentComponent_artist$data = {
 *   +name: string
 * }
 *
 * export type ExampleFragmentComponent_artist$key = { ... }
 */

import type { ExampleFragmentComponent_artist$key } from "__generated__/ExampleFragmentComponent_artist.graphql"

type Props = {
  artist: ExampleFragmentComponent_artist$key,
};

export default ExampleFragmentComponent(props) {
  // data is of type ExampleFragmentComponent_artist$data
  const data = useFragment(
    graphql`
      fragment ExampleFragmentComponent_artist on Artist {
        biography
      }
    `,
    props.artist,
  );

  return <div>About the artist: {props.artist.biography}</div>;
}
```

  </TabItem>

  <TabItem value="TypeScript">

```javascript
/**
 * export type ExampleFragmentComponent_artist$data = {
 *   readonly name: string
 * }
 *
 * export type ExampleFragmentComponent_artist$key = { ... }
 */

import { ExampleFragmentComponent_artist$key } from "__generated__/ExampleFragmentComponent_artist.graphql"

interface Props {
  artist: ExampleFragmentComponent_artist$key,
};

export default ExampleFragmentComponent(props: Props) {
  // data is of type ExampleFragmentComponent_artist$data
  const data = useFragment(
    graphql`
      fragment ExampleFragmentComponent_artist on Artist {
        biography
      }
    `,
    props.artist,
  );

  return <div>About the artist: {props.artist.biography}</div>;
}
```

  </TabItem>
</Tabs>

## Fragment references

The opaque identifier described in [data-masking] that a child container expects to receive from its parent, which represents the child container’s fragment spread inside the parent’s fragment.

<OssOnly>

:::important
Please read [this important caveat](#single-artifact-directory) about actually enabling type-safe fragment reference checking.
:::

</OssOnly>

Consider a component that [composes](../../guided-tour/rendering/fragments/#composing-fragments) the above fragment component example. In this example, the emitted type-information of the child component receives a unique opaque identifier type, called a fragment reference, which the type-information emitted for the parent’s fragment references in the location where the child’s fragment is spread. Thus ensuring that the child’s fragment is spread into the parent’s fragment _and_ the correct fragment reference is passed to the child component at runtime.

<Tabs
  defaultValue={fbContent({internal: 'Flow', external: 'TypeScript'})}
  values={[
    {label: 'Flow', value: 'Flow'},
    {label: 'TypeScript', value: 'TypeScript'},
  ]}>
  <TabItem value="Flow">

```javascript
import { ExampleFragmentComponent } from "./ExampleFragmentComponent"

/**
 * import type { ExampleFragmentComponent_artist$fragmentType } from "ExampleFragmentComponent_artist.graphql";
 *
 * export type ExampleQuery$data = {
 *   +artist: ?{
 *     +name: ?string,
 *     +$fragmentSpreads: ExampleFragmentComponent_artist$fragmentType,
 *   }
 * };
 * export type ExampleQuery$variables = {
 *   +artistID: string,
 * }
 * export type ExampleQuery = {
 *   +variables: ExampleQuery$variables,
 *   +response: ExampleQuery$data,
 * }
 */

// data is of type ExampleQuery$data
const data = useLazyLoadQuery(
  graphql`
    query ExampleQuery($artistID: ID!) {
      artist(id: $artistID) {
        name
        ...ExampleFragmentComponent_artist
      }
    }
  `,
  {artistID: 'banksy'},
);

// Here only `data.artist.name` is directly visible,
// the marker prop $fragmentSpreads indicates that `data.artist`
// can be used for the component expecting this fragment spread.
return <ExampleFragmentComponent artist={data.artist} />;
```

  </TabItem>

  <TabItem value="TypeScript">

```javascript
import { ExampleFragmentComponent } from "./ExampleFragmentComponent"

/**
 * import { ExampleFragmentComponent_artist$fragmentType } from "ExampleFragmentComponent_artist.graphql";
 *
 * export type ExampleQuery$data = {
 *   readonly artist?: {
 *     readonly name: ?string,
 *     readonly " $fragmentSpreads": ExampleFragmentComponent_artist$fragmentType
 *   }
 * }
 * export type ExampleQuery$variables = {
 *   readonly artistID: string
 * }
 * export type ExampleQuery = {
 *   readonly variables: ExampleQuery$variables
 *   readonly response: ExampleQuery$data
 * }
 */

// data is of type ExampleQuery$data
const data = useLazyLoadQuery(
  graphql`
    query ExampleQuery($artistID: ID!) {
      artist(id: $artistID) {
        name
        ...ExampleFragmentComponent_artist
      }
    }
  `,
  {artistID: 'banksy'},
);

// Here only `data.artist.name` is directly visible,
// the marker prop $fragmentSpreads indicates that `data.artist`
// can be used for the component expecting this fragment spread.
return <ExampleFragmentComponent artist={data.artist} />;
```

  </TabItem>
</Tabs>

<OssOnly>

## Single artifact directory

An important caveat to note is that by default strict fragment reference type-information will _not_ be emitted, instead they will be typed as `any` and would allow you to pass in any data to the child component.

To enable this feature, you will have to tell the compiler to store all the artifacts in a single directory, by specifying the `artifactDirectory` in the
compiler configuration:

```
{
  // package.json
  "relay": {
    "artifactDirectory": "./src/__generated__",
    ...
  },
  ...
}
```

…and additionally inform the babel plugin in your `.babelrc` config where to look for the artifacts:

```json
{
  "plugins": [
    ["relay", { "artifactDirectory": "./src/__generated__" }]
  ]
}
```

It is recommended to alias this directory in your module resolution configuration such that you don’t need to specify relative paths in your source files. This is what is also done in the above examples, where artifacts are imported from a `__generated__` alias, rather than relative paths like `../../../../__generated__`.

### Background information

The reason is that `relay-compiler` and its artifact emission is stateless. Meaning that it does not keep track of locations of original source files and where the compiler previously saved the accompanying artifact on disk. Thus, if the compiler were to emit artifacts that try to import fragment reference types from _other_ artifacts, the compiler would:

-   first need to know where on disk that other artifact exists;
-   and update imports when the other artifact changes location on disk.

Facebook uses a module system called [Haste], in which all source files are considered in a flat namespace. This means that an import declaration does not need to specify the path to another module and thus there is no need for the compiler to ever consider the above issues. I.e. an import only needs to specify the basename of the module filename and Haste takes care of actually finding the right module at import time. Outside of Facebook, however, usage of the Haste module system is non-existent nor encouraged, thus the decision to not import fragment reference types but instead type them as `any`.

At its simplest, we can consider Haste as a single directory that contains all module files, thus all module imports always being safe to import using relative sibling paths. This is what is achieved by the single artifact directory feature. Rather than co-locating artifacts with their source files, all artifacts are stored in a single directory, allowing the compiler to emit imports of fragment reference types.

</OssOnly>

[data-masking]: ../../principles-and-architecture/thinking-in-relay#data-masking

[Haste]: https://twitter.com/dan_abramov/status/758655309212704768

<DocsRating />

---

### Principles And Architecture Compiler Architecture (`website/docs/principles-and-architecture/compiler-architecture.mdx`)

---
id: compiler-architecture
title: Compiler Architecture
slug: /principles-and-architecture/compiler-architecture/
description: Relay compiler architecture guide
keywords:
- compiler
- architecture
- transform
---

import DocsRating from '@site/src/core/DocsRating';

The compiler is a set of modules designed to extract GraphQL documents from across a codebase, transform/optimize them, and generate build artifacts. Examples of common types of artifacts include optimized GraphQL to persist to your server, runtime representations of the queries for use with GraphQL clients such as the Relay runtime, or generated source code for use with GraphQL frameworks for compiled languages (Java/Swift/etc).

## Data Flow

The high-level flow of data through the compiler is represented in the following diagram:

```

                   ┌─────────────┐┌─────────────┐
                   │   GraphQL   ││   Schema    │
                   └─────────────┘└─────────────┘
                          │              │              parse
                          └───────┬──────┘
                                  ▼
                   ┌────────────────────────────┐
                   │      CompilerContext       │
                   │                            │
                   │   ┌─────┐ ┌─────┐ ┌─────┐  │──┐
                   │   │ IR  │ │ IR  │ │ ... │  │  │
                   │   └─────┘ └─────┘ └─────┘  │  │
                   └────────────────────────────┘  │  transform/
                          │    │      ▲            │   optimize
                          │    │      └────────────┘
                          │    │
                          │    └──────────┐
                          │  print        │  codegen
                          ▼               ▼
                   ┌─────────────┐ ┌─────────────┐
                   │   GraphQL   │ │  Artifacts  │
                   └─────────────┘ └─────────────┘
```

1.  GraphQL text is extracted from source files and "parsed" into an intermediate representation (IR) using information from the schema.
2.  The set of IR documents forms a CompilerContext, which is then transformed and optimized.
3.  Finally, GraphQL is printed (e.g. to files, saved to a database, etc) and any artifacts are generated.

## Data Types & Modules

The compiler module is composed of a set of core building blocks as well as a helper that packages them together in an easy to use API. Some of the main data types and modules in the compiler are as follows:

-   `IR` (Intermediate Representation): an (effectively immutable) representation of a GraphQL document (query, fragment, field, etc) as a tree structure, including type information from a schema. Compared to the standard GraphQL AST (produced by e.g. `graphql-js`) the main difference is that it encodes more of the semantics of GraphQL. For example, conditional branches (`@include` and `@skip`) are represented directly, making it easier to target optimizations for these directives (One such optimization is to merge sibling fields with the same condition, potentially reducing the number of conditionals that must be evaluated at runtime).
-   `CompilerContext`: an immutable representation of a corpus of GraphQL documents. It contains the schema and a mapping of document names to document representations (as IR, see above).
-   `Transform`: a "map"-like function that accepts a `CompilerContext` as input and returns a new, modified context as output. Examples below.
-   `Parser`: Converts a GraphQL schema and raw GraphQL text into typed IR objects.
-   `Printer`: a function that accepts IR and converts it to a GraphQL string.

The `RelayCompiler` module is a helper class that demonstrates one way of combining these primitives. It takes IR transforms, and given IR definitions, constructs a CompilerContext from them, transforming them, and generating output artifacts intended for use with Relay runtime.

## Transforms

One of the main goals of the compiler is to provide a consistent platform for writing tools that transform or optimize GraphQL. This includes the ability to experiment with new directives by transforming them away at compile time. Transform functions should typically perform a single type of modification - it's expected that an app will have multiple transforms configured in the compiler instance.

Here are a few examples of some of the included transforms:

-   `FlattenTransform`: Reduces extraneous levels of indirection in a query, inlining fields from anonymous fragments wherever they match the parent type. This can be beneficial when generating code to read the results of a query or process query results, as it reduces duplicate field processing. For example:

```
# before: `id` is processed twice
foo { # type FooType
   id
   ... on FooType { # matches the parent type, so this is extraneous
     id
   }
 }

 # after: `id` is processed once
 foo {
   id
 }
```

-   `SkipRedundantNodeTransform`: A more advanced version of flattening, this eliminates more complex cases of field duplication such as when a field is fetched both unconditionally and conditionally, or is fetched by two different sub-fragments. For example:

```
# before: `id` processed up to 2x
foo {
  bar {
    id
  }
  ... on FooType @include(if: $cond) { # can't be flattened due to conditional
    id # but this field is guaranteed to be fetched regardless
  }
}

# after: `id` processed at most once
foo {
  bar {
    id
  }
}
```

<DocsRating />

---

### Principles And Architecture Runtime Architecture (`website/docs/principles-and-architecture/runtime-architecture.mdx`)

---
id: runtime-architecture
title: Runtime Architecture
slug: /principles-and-architecture/runtime-architecture/
description: Relay runtime architecture guide
keywords:
- runtime
- architecture
- store
- DataID
- Record
- RecordSource
---

import DocsRating from '@site/src/core/DocsRating';

The Relay runtime is a full-featured GraphQL client that is designed for high performance even on low-end mobile devices and is capable of scaling to large, complex apps. The runtime API is not intended to be used directly in product code, but rather to provide a foundation for building higher-level product APIs such as React/Relay. This foundation includes:

-   A normalized, in-memory object graph/cache.
-   An optimized "write" operation for updating the cache with the results of queries/mutations/subscriptions.
-   A mechanism for reading data from the cache and subscribing for updates when these results change due to a mutation, subscription update, etc.
-   Garbage collection to evict entries from the cache when they can no longer be referenced by any view.
-   A generic mechanism for intercepting data prior to publishing it to the cache and either synthesizing new data or merging new and existing data together (which among other things enables the creation of a variety of pagination schemes).
-   Mutations with optimistic updates and the ability to update the cache with arbitrary logic.
-   Support for live queries where supported by the network/server.
-   Core primitives to enable subscriptions.
-   Core primitives for building offline/persisted caching.

## Data Types

-   `DataID` (type): A globally unique or client-generated identifier for a record, stored as a string.
-   `Record` (type): A representation of a distinct data entity with an identity, type, and fields. Note that the actual runtime representation is opaque to the system: all accesses to `Record` objects (including record creation) is mediated through the `RelayModernRecord` module. This allows the representation itself to be changed in a single place (e.g. to use `Map`s or a custom class). It is important that other code does not assume that `Record`s will always be plain objects.
-   `RecordSource` (type): A collection of records keyed by their data ID, used both to represent the cache and updates to it. For example the store's record cache is a `RecordSource` and the results of queries/mutations/subscriptions are normalized into `RecordSource`s that are published to a store. Sources also define methods for asynchronously loading records in order to (eventually) support offline use-cases. Currently the only implementation of this interface is `RelayInMemoryRecordSource`; future implementations may add support for loading records from disk.
-   `Store` (type): The source of truth for an instance of `RelayRuntime`, holding the canonical set of records in the form of a `RecordSource` (though this is not required). Currently the only implementation is `RelayModernStore`.
-   `Network` (type): Provides methods for fetching query data from and executing mutations against an external data source.
-   `Environment` (type): Represents an encapsulated environment combining a `Store` and `Network`, providing a high-level API for interacting with both. This is the main public API of `RelayRuntime`.

Types for working with queries and their results include:

-   `Selector` (type): A selector defines the starting point for a traversal into the graph for the purposes of targeting a subgraph, combining a GraphQL fragment, variables, and the Data ID for the root object from which traversal should progress. Intuitively, this "selects" a portion of the object graph.
-   `Snapshot` (type): The (immutable) results of executing a `Selector` at a given point in time. This includes the selector itself, the results of executing it, and a list of the Data IDs from which data was retrieved (useful in determining when these results might change).

## Data Model

Relay Runtime is designed for use with GraphQL schemas that describe **object graphs** in which objects have a type, an identity, and a set of fields with values. Objects may reference each other, which is represented by fields whose values are one or more other objects in the graph [1]. To distinguish from JavaScript `Object`s, these units of data are referred to as `Record`s. Relay represents both its internal cache as well as query/mutation/etc results as a mapping of **data ID**s to **records**. The data ID is the unique (with respect to the cache) identifier for a record - it may be the value of an actual `id` field or based on the path to the record from the nearest object with an `id` (such path-based ids are called **client ids**). Each `Record` stores its data ID, type, and any fields that have been fetched. Multiple records are stored together as a `RecordSource`: a mapping of data IDs to `Record` instances.

For example, a user and their address might be represented as follows:

```

// GraphQL Fragment
fragment on User {
  id
  name
  address {
    city
  }
}

// Response
{
  id: '842472',
  name: 'Joe',
  address: {
    city: 'Seattle',
  }
}

// Normalized Representation
RecordSource {
  '842472': Record {
    __id: '842472',
    __typename: 'User', // the type is known statically from the fragment
    id: '842472',
    name: 'Joe',
    address: {__ref: 'client:842472:address'}, // link to another record
  },
  'client:842472:address': Record {
    // A client ID, derived from the path from parent & parent's ID
    __id: 'client:842472:address',
    __typename: 'Address',
    city: 'Seattle',
  }
}
```

[1] Note that GraphQL itself does not impose this constraint, and Relay Runtime may also be used for schemas that do not conform to it. For example, both systems can be used to query a single denormalized table. However, many of the features that Relay Runtime provides, such as caching and normalization, work best when the data is represented as a normalized graph with stable identities for discrete pieces of information.

### Store Operations

The `Store` is the source of truth for application data and provides the following core operations.

-   `lookup(selector: Selector): Snapshot`: Reads the results of a selector from the store, returning the value given the data currently in the store.

-   `subscribe(snapshot: Snapshot, callback: (snapshot: Snapshot) => void): Disposable`: Subscribe to changes to the results of a selector. The callback is called when data has been published to the store that would cause the results of the snapshot's selector to change.

-   `publish(source: RecordSource): void`: Update the store with new information. All updates to the store are expressed in this form, including the results of queries/mutation/subscriptions as well as optimistic mutation updates. All of those operations internally create a new `RecordSource` instance and ultimately publish it to the store. Note that `publish()` does _not_ immediately update any `subscribe()`-ers. Internally, the store compares the new `RecordSource` with its internal source, updating it as necessary:
    -   Records that exist only in the published source are added to the store.
    -   Records that exist in both are merged into a new record (inputs unchanged), with the result added to the store.
    -   Records that are null in the published source are deleted (set to null) in the store.
    -   Records with a special sentinel value are removed from the store. This supports un-publishing optimistically created records.

-   `notify(): void`: Calls any `subscribe()`-ers whose results have changed due to intervening `publish()`-es. Separating `publish()` and `notify()` allows for multiple payloads to be published before performing any downstream update logic (such as rendering).

-   `retain(selector: Selector): Disposable`: Ensure that all the records necessary to fulfill the given selector are retained in-memory. The records will not be eligible for garbage collection until the returned reference is disposed.

### Example Data Flow: Fetching Query Data

```

               ┌───────────────────────┐
               │         Query         │
               └───────────────────────┘
                           │
                           ▼
                                             ┌ ─ ─ ─ ┐
                         fetch ◀────────────▶ Server
                                             └ ─ ─ ─ ┘
                           │
                     ┌─────┴───────┐
                     ▼             ▼
               ┌──────────┐  ┌──────────┐
               │  Query   │  │ Response │
               └──────────┘  └──────────┘
                     │             │
                     └─────┬───────┘
                           │
                           ▼
                       normalize
                           │
                           ▼
               ┌───────────────────────┐
               │     RecordSource      │
               │                       │
               │┌──────┐┌──────┐┌─────┐│
               ││Record││Record││ ... ││
               │└──────┘└──────┘└─────┘│
               └───────────────────────┘

```

1.  The query is fetched from the network.
2.  The query and response are traversed together, extracting the results into `Record` objects which are added to a fresh `RecordSource`.

This fresh `RecordSource` would then be published to the store:

```

                        publish
                           │
                           ▼
             ┌───────────────────────────┐
             │           Store           │
             │ ┌───────────────────────┐ │
             │ │     RecordSource      │ │
             │ │                       │ │
             │ │┌──────┐┌──────┐┌─────┐│ │
             │ ││Record││Record││ ... ││ │ <--- records are updated
             │ │└──────┘└──────┘└─────┘│ │
             │ └───────────────────────┘ │
             │ ┌───────────────────────┐ │
             │ │     Subscriptions     │ │
             │ │                       │ │
             │ │┌──────┐┌──────┐┌─────┐│ │
             │ ││ Sub. ││ Sub. ││ ... ││ │ <--- subscriptions do not fire yet
             │ │└──────┘└──────┘└─────┘│ │
             │ └───────────────────────┘ │
             └───────────────────────────┘

```

Publishing the results updates the store but does _not_ immediately notify any subscribers. This is accomplished by calling `notify()`...

```

                        notify
                           │
                           ▼
             ┌───────────────────────────┐
             │           Store           │
             │ ┌───────────────────────┐ │
             │ │     RecordSource      │ │
             │ │                       │ │
             │ │┌──────┐┌──────┐┌─────┐│ │
             │ ││Record││Record││ ... ││ │
             │ │└──────┘└──────┘└─────┘│ │
             │ └───────────────────────┘ │
             │ ┌───────────────────────┐ │
             │ │     Subscriptions     │ │
             │ │                       │ │
             │ │┌──────┐┌──────┐┌─────┐│ │
             │ ││  Sub.││  Sub.││  ...││ │ <--- affected subscriptions fire
             │ │└──────┘└──────┘└─────┘│ │
             │ └───┼───────┼───────┼───┘ │
             └─────┼───────┼───────┼─────┘
                   │       │       │
                   ▼       │       │
               callback    │       │
                           ▼       │
                       callback    │
                                   ▼
                               callback

```

...which calls the callbacks for any `subscribe()`-ers whose results have changed. Each subscription is checked as follows:

1.  First, the list of data IDs that have changed since the last `notify()` is compared against data IDs listed in the subscription's latest `Snapshot`. If there is no overlap, the subscription's results cannot possibly have changed (if you imagine the graph visually, there is no overlap between the part of the graph that changed and the part that is selected). In this case the subscription is ignored, otherwise processing continues.
2.  Second, any subscriptions that do have overlapping data IDs are re-read, and the new/previous results are compared. If the result has not changed, the subscription is ignored (this can occur if a field of a record changed that is not relevant to the subscription's selector), otherwise processing continues.
3.  Finally, subscriptions whose data actually changed are notified via their callback.

### Example Data Flow: Reading and Observing the Store

Products access the store primarily via `lookup()` and `subscribe()`. Lookup reads the initial results of a fragment, and subscribe observes that result for any changes. Note that the output of `lookup()` - a `Snapshot` - is the input to `subscribe()`. This is important because the snapshot contains important information that can be used to optimize the subscription - if `subscribe()` accepted only a `Selector`, it would have to re-read the results in order to know what to subscribe to, which is less efficient.

Therefore a typical data flow is as follows - note that this flow is managed automatically by higher-level APIs such as React/Relay. First a component will lookup the results of a selector against a record source (e.g. the store's canonical source):

```

    ┌───────────────────────┐       ┌──────────────┐
    │     RecordSource      │       │              │
    │                       │       │              │
    │┌──────┐┌──────┐┌─────┐│       │   Selector   │
    ││Record││Record││ ... ││       │              │
    │└──────┘└──────┘└─────┘│       │              │
    └───────────────────────┘       └──────────────┘
                │                           │
                │                           │
                └──────────────┬────────────┘
                               │
                               │  lookup
                               │  (read)
                               │
                               ▼
                        ┌─────────────┐
                        │             │
                        │  Snapshot   │
                        │             │
                        └─────────────┘
                               │
                               │  render, etc
                               │
                               ▼

```

Next, it will `subscribe()` using this snapshot in order to be notified of any changes - see the above diagram for `publish()` and `notify()`.

<DocsRating />

---

### Principles And Architecture Thinking In Graphql (`website/docs/principles-and-architecture/thinking-in-graphql.mdx`)

---
id: thinking-in-graphql
title: Thinking in GraphQL
slug: /principles-and-architecture/thinking-in-graphql/
description: Relay guide to thinking in GraphQL
keywords:
- GraphQL
---

import DocsRating from '@site/src/core/DocsRating';

GraphQL presents new ways for clients to fetch data by focusing on the needs of product developers and client applications. It provides a way for developers to specify the precise data needed for a view and enables a client to fetch that data in a single network request. Compared to traditional approaches such as REST, GraphQL helps applications to fetch data more efficiently (compared to resource-oriented REST approaches) and avoid duplication of server logic (which can occur with custom endpoints). Furthermore, GraphQL helps developers to decouple product code and server logic. For example, a product can fetch more or less information without requiring a change to every relevant server endpoint. It's a great way to fetch data.

In this article we'll explore what it means to build a GraphQL client framework and how this compares to clients for more traditional REST systems. Along the way we'll look at the design decisions behind Relay and see that it's not just a GraphQL client but also a framework for _declarative data-fetching_. Let's start at the beginning and fetch some data!

## Fetching Data

Imagine we have a simple application that fetches a list of stories, and some details about each one. Here's how that might look in resource-oriented REST:

```javascript
// Fetch the list of story IDs but not their details:
rest.get('/stories').then(stories =>
  // This resolves to a list of items with linked resources:
  // `[ { href: "http://.../story/1" }, ... ]`
  Promise.all(stories.map(story =>
    rest.get(story.href) // Follow the links
  ))
).then(stories => {
  // This resolves to a list of story items:
  // `[ { id: "...", text: "..." } ]`
  console.log(stories);
});
```

Note that this approach requires _n+1_ requests to the server: 1 to fetch the list, and _n_ to fetch each item. With GraphQL we can fetch the same data in a single network request to the server (without creating a custom endpoint that we'd then have to maintain):

```javascript
graphql.get(`query { stories { id, text } }`).then(
  stories => {
    // A list of story items:
    // `[ { id: "...", text: "..." } ]`
    console.log(stories);
  }
);
```

So far we're just using GraphQL as a more efficient version of typical REST approaches. Note two important benefits in the GraphQL version:

-   All data is fetched in a single round trip.
-   The client and server are decoupled: the client specifies the data needed instead of _relying on_ the server endpoint to return the correct data.

For a simple application that's already a nice improvement.

## Client Caching

Repeatedly refetching information from the server can get quite slow. For example, navigating from the list of stories, to a list item, and back to the list of stories means we have to refetch the whole list. We'll solve this with the standard solution: _caching_.

In a resource-oriented REST system, we can maintain a **response cache** based on URIs:

```javascript
var _cache = new Map();
rest.get = uri => {
  if (!_cache.has(uri)) {
    _cache.set(uri, fetch(uri));
  }
  return _cache.get(uri);
};
```

Response-caching can also be applied to GraphQL. A basic approach would work similarly to the REST version. The text of the query itself can be used as a cache key:

```javascript
var _cache = new Map();
graphql.get = queryText => {
  if (!_cache.has(queryText)) {
    _cache.set(queryText, fetchGraphQL(queryText));
  }
  return _cache.get(queryText);
};
```

Now, requests for previously cached data can be answered immediately without making a network request. This is a practical approach to improving the perceived performance of an application. However, this method of caching can cause problems with data consistency.

## Cache Consistency

With GraphQL it is very common for the results of multiple queries to overlap. However, our response cache from the previous section doesn't account for this overlap — it caches based on distinct queries. For example, if we issue a query to fetch stories:

```graphql
query { stories { id, text, likeCount } }
```

and then later refetch one of the stories whose `likeCount` has since been incremented:

```graphql
query { story(id: "123") { id, text, likeCount } }
```

We'll now see different `likeCount`s depending on how the story is accessed. A view that uses the first query will see an outdated count, while a view using the second query will see the updated count.

### Caching A Graph

The solution to caching GraphQL is to normalize the hierarchical response into a flat collection of **records**. Relay implements this cache as a map from IDs to records. Each record is a map from field names to field values. Records may also link to other records (allowing it to describe a cyclic graph), and these links are stored as a special value type that references back into the top-level map. With this approach each server record is stored _once_ regardless of how it is fetched.

Here's an example query that fetches a story's text and its author's name:

```graphql
query {
  story(id: "1") {
    text,
    author {
      name
    }
  }
}
```

And here's a possible response:

```json
{
  "query": {
    "story": {
      "text": "Relay is open-source!",
      "author": {
        "name": "Jan"
      }
    }
  }
}
```

Although the response is hierarchical, we'll cache it by flattening all the records. Here is an example of how Relay would cache this query response:

```javascript
Map {
  // `story(id: "1")`
  1: Map {
    text: 'Relay is open-source!',
    author: Link(2),
  },
  // `story.author`
  2: Map {
    name: 'Jan',
  },
};
```

This is only a simple example: in reality the cache must handle one-to-many associations and pagination (among other things).

### Using The Cache

So how do we use this cache? Let's look at two operations: writing to the cache when a response is received, and reading from the cache to determine if a query can be fulfilled locally (the equivalent to `_cache.has(key)` above, but for a graph).

### Populating The Cache

Populating the cache involves walking a hierarchical GraphQL response and creating or updating normalized cache records. At first it may seem that the response alone is sufficient to process the response, but in fact this is only true for very simple queries. Consider `user(id: "456") { photo(size: 32) { uri } }` — how should we store `photo`? Using `photo` as the field name in the cache won't work because a different query might fetch the same field but with different argument values (e.g. `photo(size: 64) {...}`). A similar issue occurs with pagination. If we fetch the 11th to 20th stories with `stories(first: 10, offset: 10)`, these new results should be _appended_ to the existing list.

Therefore, a normalized response cache for GraphQL requires processing payloads and queries in parallel. For example, the `photo` field from above might be cached with a generated field name such as `photo_size(32)` in order to uniquely identify the field and its argument values.

### Reading From Cache

To read from the cache we can walk a query and resolve each field. But wait: that sounds _exactly_ like what a GraphQL server does when it processes a query. And it is! Reading from the cache is a special case of an executor where a) there's no need for user-defined field functions because all results come from a fixed data structure and b) results are always synchronous — we either have the data cached or we don't.

Relay implements several variations of **query traversal**: operations that walk a query alongside some other data such as the cache or a response payload. For example, when a query is fetched Relay performs a "diff" traversal to determine what fields are missing (much like React diffs virtual DOM trees). This can reduce the amount of data fetched in many common cases and even allow Relay to avoid network requests at all when queries are fully cached.

### Cache Updates

Note that this normalized cache structure allows overlapping results to be cached without duplication. Each record is stored once regardless of how it is fetched. Let's return to the earlier example of inconsistent data and see how this cache helps in that scenario.

The first query was for a list of stories:

```graphql
query { stories { id, text, likeCount } }
```

With a normalized response cache, a record would be created for each story in the list. The `stories` field would store links to each of these records.

The second query refetched the information for one of those stories:

```graphql
query { story(id: "123") { id, text, likeCount } }
```

When this response is normalized, Relay can detect that this result overlaps with existing data based on its `id`. Rather than create a new record, Relay will update the existing `123` record. The new `likeCount` is therefore available to _both_ queries, as well as any other query that might reference this story.

## Data/View Consistency

A normalized cache ensures that the _cache_ is consistent. But what about our views? Ideally, our React views would always reflect the current information from the cache.

Consider rendering the text and comments of a story along with the corresponding author names and photos. Here's the GraphQL query:

```graphql
query {
  story(id: "1") {
    text,
    author { name, photo },
    comments {
      text,
      author { name, photo }
    }
  }
}
```

After initially fetching this story our cache might be as follows. Note that the story and comment both link to the same record as `author`:

```
// Note: This is pseudo-code for `Map` initialization to make the structure
// more obvious.
Map {
  // `story(id: "1")`
  1: Map {
    text: 'got GraphQL?',
    author: Link(2),
    comments: [Link(3)],
  },
  // `story.author`
  2: Map {
    name: 'Yuzhi',
    photo: 'http://.../photo1.jpg',
  },
  // `story.comments[0]`
  3: Map {
    text: 'Here\'s how to get one!',
    author: Link(2),
  },
}
```

The author of this story also commented on it — quite common. Now imagine that some other view fetches new information about the author, and her profile photo has changed to a new URI. Here's the _only_ part of our cached data that changes:

```
Map {
  ...
  2: Map {
    ...
    photo: 'http://.../photo2.jpg',
  },
}
```

The value of the `photo` field has changed; and therefore the record `2` has also changed. And that's it. Nothing else in the _cache_ is affected. But clearly our _view_ needs to reflect the update: both instances of the author in the UI (as story author and comment author) need to show the new photo.

A standard response is to "just use immutable data structures" — but let's see what would happen if we did:

```
ImmutableMap {
  1: ImmutableMap // same as before
  2: ImmutableMap {
    ... // other fields unchanged
    photo: 'http://.../photo2.jpg',
  },
  3: ImmutableMap // same as before
}
```

If we replace `2` with a new immutable record, we'll also get a new immutable instance of the cache object. However, records `1` and `3` are untouched. Because the data is normalized, we can't tell that `story`'s contents have changed just by looking at the `story` record alone.

### Achieving View Consistency

There are a variety of solutions for keeping views up to date with a flattened cache. The approach that Relay takes is to maintain a mapping from each UI view to the set of IDs it references. In this case, the story view would subscribe to updates on the story (`1`), the author (`2`), and the comments (`3` and any others). When writing data into the cache, Relay tracks which IDs are affected and notifies _only_ the views that are subscribed to those IDs. The affected views re-render, and unaffected views opt-out of re-rendering for better performance (Relay provides a safe but effective default `shouldComponentUpdate`). Without this strategy, every view would re-render for even the tiniest change.

Note that this solution will also work for _writes_: any update to the cache will notify the affected views, and writes are just another thing that updates the cache.

## Mutations

So far we've looked at the process of querying data and keeping views up to date, but we haven't looked at writes. In GraphQL, writes are called **mutations**. We can think of them as queries with side effects. Here's an example of calling a mutation that might mark a given story as being liked by the current user:

```graphql
// Give a human-readable name and define the types of the inputs,
// in this case the id of the story to mark as liked.
mutation StoryLike($storyID: String) {
   // Call the mutation field and trigger its side effects
   storyLike(storyID: $storyID) {
     // Define fields to re-fetch after the mutation completes
     likeCount
   }
}
```

Notice that we're querying for data that _may_ have changed as a result of the mutation. An obvious question is: why can't the server just tell us what changed? The answer is: it's complicated. GraphQL abstracts over _any_ data storage layer (or an aggregation of multiple sources), and works with any programming language. Furthermore, the goal of GraphQL is to provide data in a form that is useful to product developers building a view.

We've found that it's common for the GraphQL schema to differ slightly or even substantially from the form in which data is stored on disk. Put simply: there isn't always a 1:1 correspondence between data changes in your underlying _data storage_ (disk) and data changes in your _product-visible schema_ (GraphQL). The perfect example of this is privacy: returning a user-facing field such as `age` might require accessing numerous records in our data-storage layer to determine if the active user is even allowed to _see_ that `age` (Are we friends? Is my age shared? Did I block you? etc.).

Given these real-world constraints, the approach in GraphQL is for clients to query for things that may change after a mutation. But what exactly do we put in that query? During the development of Relay we explored several ideas — let's look at them briefly in order to understand why Relay uses the approach that it does:

-   Option 1: Re-fetch everything that the app has ever queried. Even though only a small subset of this data will actually change, we'll still have to wait for the server to execute the _entire_ query, wait to download the results, and wait to process them again. This is very inefficient.

-   Option 2: Re-fetch only the queries required by actively rendered views. This is a slight improvement over option 1. However, cached data that _isn't_ currently being viewed won't be updated. Unless this data is somehow marked as stale or evicted from the cache subsequent queries will read outdated information.

-   Option 3: Re-fetch a fixed list of fields that _may_ change after the mutation. We'll call this list a **fat query**. We found this to also be inefficient because typical applications only render a subset of the fat query, but this approach would require fetching all of those fields.

-   Option 4 (Relay): Re-fetch the intersection of what may change (the fat query) and the data in the cache. In addition to the cache of data Relay also remembers the queries used to fetch each item. These are called **tracked queries**. By intersecting the tracked and fat queries, Relay can query exactly the set of information the application needs to update and nothing more.

## Data-Fetching APIs

So far we looked at the lower-level aspects of data-fetching and saw how various familiar concepts translate to GraphQL. Next, let's step back and look at some higher-level concerns that product developers often face around data-fetching:

-   Fetching all the data for a view hierarchy.
-   Managing asynchronous state transitions and coordinating concurrent requests.
-   Managing errors.
-   Retrying failed requests.
-   Updating the local cache after receiving query/mutation responses.
-   Queuing mutations to avoid race conditions.
-   Optimistically updating the UI while waiting for the server to respond to mutations.

We've found that typical approaches to data-fetching — with imperative APIs — force developers to deal with too much of this non-essential complexity. For example, consider _optimistic UI updates_. This is a way of giving the user feedback while waiting for a server response. The logic of _what_ to do can be quite clear: when the user clicks "like", mark the story as being liked and send the request to the server. But the implementation is often much more complex. Imperative approaches require us to implement all of those steps: reach into the UI and toggle the button, initiate a network request, retry it if necessary, show an error if it fails (and untoggle the button), etc. The same goes for data-fetching: specifying _what_ data we need often dictates _how_ and _when_ it is fetched. Next, we'll explore our approach to solving these concerns with **Relay**.

<DocsRating />

---

### Principles And Architecture Thinking In Relay (`website/docs/principles-and-architecture/thinking-in-relay.mdx`)

---
id: thinking-in-relay
title: Thinking in Relay
slug: /principles-and-architecture/thinking-in-relay/
description: Relay guide to thinking in Relay
---

import DocsRating from '@site/src/core/DocsRating';

Relay's approach to data-fetching is heavily inspired by our experience with React. In particular, React breaks complex interfaces into reusable **components**, allowing developers to reason about discrete units of an application in isolation, and reducing the coupling between disparate parts of an application. Even more important is that these components are **declarative**: they allow developers to specify _what_ the UI should look like for a given state, and not have to worry about _how_ to show that UI. Unlike previous approaches that used imperative commands to manipulate native views (e.g. the DOM), React uses a UI description to automatically determine the necessary commands.

Let's look at some product use-cases to understand how we incorporated these ideas into Relay. We'll assume a basic familiarity with React.

## Fetching Data For a View

In our experience, the overwhelming majority of products want one specific behavior: fetch all the data for a view hierarchy while displaying a loading indicator, and then render the entire view once the data is available.

One solution is to have a root component declare and fetch the data required by it and all of its children. However, this would introduce coupling: any change to a child component would require changing any root component that might render it! This coupling could mean a greater chance for bugs and slow the pace of development.

Another logical approach is to have each component declare and fetch the data it requires. This sounds great. However, the problem is that a component may render different children based on the data it received. So, nested components will be unable to render and begin fetching their data until parent components' queries have completed. In other words, *this forces data fetching to proceed in stages:* first render the root and fetch the data it needs, then render its children and fetch their data, and so on until you reach leaf components. Rendering would require multiple slow, serial roundtrips.

Relay combines the advantages of both of these approaches by allowing components to specify what data they require, but to coalesce those requirements into a single query that fetches the data for an entire subtree of components. In other words, it determines *statically* (i.e. before your application runs; at the time you write your code) the requirements for an entire view!

This is achieved with the help of GraphQL. Functional components use one or more GraphQL <a href="../../guided-tour/rendering/fragments/">fragments</a> to describe their data requirements. These fragments are then nested within other fragments, and ultimately within queries. And when such a query is fetched, Relay will make a single network request for it and all of its nested fragments. In other words, the Relay runtime is then able to make a *single network request* for all of the data required by a view!

Let's dive deeper to understand how Relay achieves this feat.

## Specifying the data requirements of a component

With Relay, the data requirements for a component are specified with <a href="../../guided-tour/rendering/fragments/">fragments</a>. Fragments are named snippets of GraphQL that specify which fields to select from an object of a particular type. Fragments are written within GraphQL literals. For example, the following declares a GraphQL literal containing a fragment which selects an author's name and photo url:

```javascript
// AuthorDetails.react.js
const authorDetailsFragment = graphql`
  fragment AuthorDetails_author on Author {
    name
    photo {
      url
    }
  }
`;
```

This data is then read out from the store by calling the `useFragment(...)` hook in a functional React component. The actual author from which to read this data is determined by the second parameter passed to `useFragment`. For example:

```javascript
// AuthorDetails.react.js
export default function AuthorDetails(props) {
  const data = useFragment(authorDetailsFragment, props.author);
  // ...
}
```

This second parameter (`props.author`) is a fragment reference. Fragment references are obtained by **spreading** a fragment into another fragment or query. Fragments cannot be fetched directly. Instead, all fragments must ultimately be spread (either directly or transitively) into a query for the data to be fetched.

Let's take a look at one such query.

## Queries

In order to fetch that data, we might declare a query which spreads `AuthorDetails_author` as follows:

```javascript
// Story.react.js
const storyQuery = graphql`
  query StoryQuery($storyID: ID!) {
    story(id: $storyID) {
      title
      author {
        ...AuthorDetails_author
      }
    }
  }
`;
```

Now, we can fetch the query by calling `const data = useLazyLoadQuery(storyQuery, {storyID})`. At this point, `data.story.author` (if it is present; all fields are nullable by default) will be a fragment reference that we can pass to `AuthorDetails`. For example:

```javascript
// Story.react.js
function Story(props) {
  const data = useLazyLoadQuery(storyQuery, props.storyId);

  return (<>
    <Heading>{data?.story.title}</Heading>
    {data?.story?.author && <AuthorDetails author={data.story.author} />}
  </>);
}
```

Note what has happened here. We made a single network request which contained the data required by *both* the `Story` component *and* the `AuthorDetails` component! When that data was available, the entire view could render in a single pass.

## Data Masking

With typical approaches to data-fetching we found that it was common for two components to have _implicit dependencies_. For example `<Story />` might use some data without directly ensuring that the data was fetched. This data would often be fetched by some other part of the system, such as `<AuthorDetails />`. Then when we changed `<AuthorDetails />` and removed that data-fetching logic, `<Story />` would suddenly and inexplicably break. These types of bugs are not always immediately apparent, especially in larger applications developed by larger teams. Manual and automated testing can only help so much: this is exactly the type of systematic problem that is better solved by a framework.

We've seen that Relay ensures that the data for a view is fetched all at once. But Relay also provide another benefit that isn't immediately obvious: **data masking**. Relay only allows components to access data they specifically ask for in GraphQL fragments, and nothing more. So if one component queries for a Story's `title`, and another for its `text`, each can see _only_ the field that they asked for. In fact, components can't even see the data requested by their _children_: that would also break encapsulation.

Relay also goes further: it uses opaque identifiers on `props` to validate that we've explicitly fetched the data for a component before rendering it. If `<Story />` renders `<AuthorDetails />` but forgets to spread its fragment, Relay will warn that the data for `<AuthorDetails />` is missing. In fact, Relay will warn _even if_ some other component happened to fetch the same data required by `<AuthorDetails />`. This warning tells us that although things _might_ work now, they're highly likely to break later.

# Conclusion

GraphQL provides a powerful tool for building efficient, decoupled client applications. Relay builds on this functionality to provide a framework for **declarative data-fetching**. By separating _what_ data to fetch from _how_ it is fetched, Relay helps developers build applications that are robust, transparent, and performant by default. It's a great complement to the component-centric way of thinking championed by React. While each of these technologies — React, Relay, and GraphQL — are powerful on their own, the combination is a **UI platform** that allows us to _move fast_ and _ship high-quality apps at scale_.

<DocsRating />

---

### Principles And Architecture Videos (`website/docs/principles-and-architecture/videos.mdx`)

---
id: videos
title: Videos
slug: /principles-and-architecture/videos/
description: Relay videos
---

import DocsRating from '@site/src/core/DocsRating';

## React Conf 2021

### Re-introducing Relay | Robert Balicki

<iframe src="https://www.youtube-nocookie.com/embed/lhVGdErZuN4" width={640} height={360} allowFullScreen={true} frameBorder="0" />

## React Conf 2019

### Data Fetching With Suspense In Relay | Joe Savona

<iframe src="https://www.youtube-nocookie.com/embed/Tl0S7QkxFE4" width={640} height={360} allowFullScreen={true} frameBorder="0" />

## Facebook F8 2019

### [Building the new Facebook.com with React, GraphQL and Relay](https://developers.facebook.com/videos/2019/building-the-new-facebookcom-with-react-graphql-and-relay/)

<iframe src="https://www.youtube-nocookie.com/embed/WxPtYJRjLL0?start=215" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen width="640" height="360" frameBorder="0"></iframe>

## Facebook F8 2017

### [The Evolution of React and GraphQL at Facebook and Beyond](https://developers.facebook.com/videos/f8-2017/the-evolution-of-react-and-graphql-at-facebook-and-beyond/)

<iframe src="https://www.facebook.com/plugins/video.php?href=https%3A%2F%2Fwww.facebook.com%2FFacebookforDevelopers%2Fvideos%2F10154614710193553%2F&show_text=0&width=640" width={640} height={360} frameBorder="0" allowFullScreen={true} />

## [Silicon Valley ReactJS Meetup](http://www.meetup.com/Silicon-Valley-ReactJS-Meetup/)

### Relay Modern: simpler, faster, more predictable ([slides](https://speakerdeck.com/wincent/relay-2-simpler-faster-more-predictable))

<iframe width={640} height={360} src="https://www.youtube-nocookie.com/embed/OEfUBN9dAI8" frameBorder="0" allowFullScreen={true} />

### Zero to GraphQL in 30 minutes

<iframe width={640} height={360} src="https://www.youtube-nocookie.com/embed/UBGzsb2UkeY" frameBorder="0" allowFullScreen={true} />

## [GraphQL Europe 2018](https://www.graphql-europe.org/)

### Data Masking in GraphQL Clients

<iframe width={640} height={360} src="https://www.youtube-nocookie.com/embed/ww5UQ50oHok" frameBorder="0" allowFullScreen={true} />

<DocsRating />

---

### Tutorial Arrays Lists (`website/docs/tutorial/arrays-lists.mdx`)

# Arrays and Lists

So far we’ve only dealt with components that have a single instance of the components they’re composed from. For example, we’re only showing a single Newsfeed story, and within that story there’s just a single author with a single profile picture. Let’s look at how to handle more than one of something.

GraphQL includes support for arrays, which in GraphQL are called *lists.* A field can be not only a single scalar value but an array of them, or not only a single edge but an array of edges. The schema specifies whether each field is a list or not, but, oddly, the GraphQL query syntax doesn’t distinguish between selecting a singular field and selecting a list — a quirky exception to the design principle that a GraphQL response should have the same shape as the query.

Request:

```
query MyQuery {
  viewer {
    contacts { // List of edges
      id // field on a single item
      name
    }
  }
}
```

Response:

```
{
  viewer: {
    contacts: [ // array in response
      {
        id: "123",
        name: "Chris",
      },
      {
        id: "789",
        name: "Sue",
      }
    ]
  }
}
```

As it happens, the schema in our example app has a `topStories` field that returns a list of Stories, as opposed to the `topStory` field we're currently using that returns just one.

To show multiple stories on our newsfeed, we just need to modify `Newsfeed.tsx` to use `topStories`.

### Step 1 — Select a list in the fragment

Open `Newsfeed.tsx` and find `NewsfeedQuery`. Replace `topStory` with `topStories`, and run `npm run relay`.

```
const NewsfeedQuery = graphql`
  query NewsfeedQuery {
    // change-line
    topStories {
      ...StoryFragment
    }
  }
`;
```

### Step 2 — Map over the list in the component

In the `Newsfeed` component, `data.topStories` will now be an array of fragment refs, each of which can be passed to a `Story` child component to render that story:

```
export default function Newsfeed({}) {
  const data = useLazyLoadQuery<NewsfeedQueryType>(NewsfeedQuery, {});
  // change-line
  const stories = data.topStories;
  return (
    <div className="newsfeed">
      // change-line
      {stories.map(story => <Story story={story} />)}
    </div>
  );
}
```

### Step 3 — Add a React key based on the node ID

At this point, you should see multiple stories on the screen! It's beginning to look like a proper newsfeed app.



However, we're also getting a React warning that we're rendering an array of components without [providing a key attribute](https://reactjs.org/docs/lists-and-keys.html).



It's always important to heed this warning, and more specifically to base keys on the identity of the things being displayed, rather than simply their indices in the array. This allows React to handle reordering and deleting items from the list correctly, since it knows which items are which even if their order changes.

Luckily, GraphQL nodes generally have IDs. We can simply select the `id` field of `story` and use it as a key:

```
const NewsfeedQuery = graphql`
  query NewsfeedQuery {
    topStories {
      // change-line
      id
      ...StoryFragment
    }
  }
`;

...

export default function Newsfeed({}) {
  const data = useLazyLoadQuery<NewsfeedQueryType>(NewsfeedQuery, {});
  const stories = data.topStories;
  return (
    <div className="newsfeed">
      {stories.map(story => (
        <Story
          // change-line
          key={story.id}
          story={story}
        />
      ))}
    </div>
  );
}
```

With that, we've got a collection of Stories on the screen. It's worth pointing out that here we're mixing individual fields with fragment spreads in the same place in our query. This means that Newsfeed can read the fields it cares about (directly from `useLazyLoadQuery`) while Story can read the fields it cares about (via `useFragment`). The *same object* both contains Newsfeed's selected field `id` and is also a fragment key for `StoryFragment`.

:::tip
GraphQL Lists are only the most basic way of dealing with collections of things. We’ll build on them to do pagination and infinite scrolling later in the tutorial, using a special system called Connections. You’ll want to use Connections in most situations where you have a collection of items — although you’ll still use GraphQL Lists as a building block.
:::

Onward!

---

### Tutorial Fragments 1 (`website/docs/tutorial/fragments-1.mdx`)

# Fragments

Fragments are one of the distinguishing features of Relay. They let each component declare its own data needs independently, while retaining the efficiency of a single query. In this section, we’ll show how to split a query up into fragments.

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

* * *

To start with, let’s say we want our Story component to show the date that the story was posted. To do that, we need some more data from the server, so we’re going to have to add a field to the query.

Go to `Newsfeed.tsx` and find `NewsfeedQuery` so that you can add the new field:

```
const NewsfeedQuery = graphql`
  query NewsfeedQuery {
    topStory {
      title
      summary
      // change-line
      createdAt // Add this line
      poster {
        name
        profilePicture {
          url
        }
      }
      thumbnail {
        url
      }
    }
  }
`;
```

Now we've updated the query, we need to run the Relay compiler so that it knows about the updated Graphql query by running `npm run relay`.

Next, go to `Story.tsx` and modify it to display the date:

```
// change-line
import Timestamp from './Timestamp';

type Props = {
  story: {
    // change-line
    createdAt: string; // Add this line
    ...
  };
};

export default function Story({story}: Props) {
  return (
    <Card>
      <PosterByline poster={story.poster} />
      <Heading>{story.title}</Heading>
      // change-line
      <Timestamp time={story.createdAt} /> // Add this line
      <Image image={story.thumbnail} width={400} height={400} />
      <StorySummary summary={story.summary} />
    </Card>
  );
}
```

The date should now appear. And thanks to GraphQL, we didn't have to write and deploy any new server code.

But if you think about it, why should you have had to modify `Newsfeed.tsx`? Shouldn’t React components be self-contained? Why should Newsfeed care about the specific data required by Story? What if the data was required by some child component of Story way down in the hierarchy? What if it was a component that was used in many different places? Then we would have to modify many components whenever its data requirements changed.

To avoid these and many other problems, we can move the data requirements for the Story component into `Story.tsx`.

We do this by splitting off `Story`’s data requirements into a *fragment* defined in `Story.tsx`. Fragments are separate pieces of GraphQL that the Relay compiler stitches together into complete queries. They allow each component to define its own data requirements, without paying the cost at runtime of each component running its own queries.



Let’s go ahead and split `Story`’s data requirements into a fragment now.

* * *

### Step 1 — Define a fragment

Add the following to `Story.tsx` (within `src/components`) above the `Story` component:

```
import { graphql } from 'relay-runtime';

const StoryFragment = graphql`
  fragment StoryFragment on Story {
    title
    summary
    createdAt
    poster {
      name
      profilePicture {
        url
      }
    }
    thumbnail {
      url
    }
  }
`;
```

Note that we’ve taken all of the selections from within `topStory` in our query and copied them into this new Fragment declaration. Like queries, fragments have a name (`StoryFragment`), which we’ll use in a moment, but they also have a GraphQL type (`Story`) that they’re “on”. This means that this fragment can be used whenever we have a Story node in the graph.

### Step 2 — Spread the fragment

Go to `Newsfeed.tsx` and modify `NewsfeedQuery` to look like this:

```
const NewsfeedQuery = graphql`
  query NewsfeedQuery {
    topStory {
      // change-line
      ...StoryFragment
    }
  }
`;
```

We’ve replaced the selections inside `topStory` with `StoryFragment`. The Relay compiler will make sure that all of Story’s data gets fetched from now on, without having to change `Newsfeed`.

### Step 3 — Call useFragment

You’ll notice that Story now renders an empty card! All the data is missing! Wasn’t Relay supposed to include the fields selected by the fragment in the `story` object obtained from `useLazyLoadQuery()`?

The reason is that Relay hides them. Unless a component specifically asks for the data for a certain fragment, that data will not be visible to the component. This is called *data masking*, and enforces that components don’t implicitly rely on another component’s data dependencies, but declare all of their dependencies within their own fragments. This keeps components self-contained and maintainable.

Without data masking, you could never remove a field from a fragment, because it would be hard to verify that some other component somewhere wasn’t using it.

To access the data selected by a fragment, we use a hook called `useFragment`. Modify `Story` to look like this:

```
import { useFragment } from 'react-relay';

export default function Story({story}: Props) {
  const data = useFragment(
    // color1
    StoryFragment,
    // color2
    story,
  );
  return (
    <Card>
      <Heading>{data.title}</Heading>
      <PosterByline poster={data.poster} />
      <Timestamp time={data.createdAt} />
      <Image image={data.thumbnail} width={400} height={400} />
      <StorySummary summary={data.summary} />
    </Card>
  );
}
```

`useFragment` takes two arguments:

* The <span className="color1">GraphQL tagged string</span> literal for the fragment we want to read
* The same <span className="color2">story object</span> as we used before, which comes from the place within a GraphQL query where we spread the fragment. This is called a *fragment key*.

It returns the data selected by that fragment.

:::tip
We’ve rewritten `story` to `data` (the data returned by `useFragment`) in all of the JSX here; make sure to do the same in your copy of the component, or it won't work.
:::

Fragment keys are the places in a GraphQL query response where a fragment was spread. For example, given the Newsfeed query:

```
query NewsfeedQuery {
  topStory {
    ...StoryFragment
  }
}
```

Then if `queryResult` is the object returned by `useLazyLoadQuery`, `queryResult.topStory` will be a fragment key for `StoryFragment`.

Technically, `queryResult.topStory` is an object that contains some hidden fields that tell Relay's `useFragment` where to look for the data it needs. The fragment key specifies both which node to read from (here there's just one story, but soon we'll have multiple stories), and what fields can be read out (the fields selected by that specific fragment). The `useFragment` hook then reads that specific information out of Relay's local data store.

:::note
As we'll see in later examples, you can spread multiple fragments into the same place in a query, and also mix fragment spreads with directly-selected fields.
:::


### Step 4 — TypeScript types for fragment refs

To complete the fragmentization, we also need to change the type definition for `Props` so that TypeScript knows this component expects to receive a fragment key instead of the raw data.

Recall that when you spread a fragment into a query (or another fragment), the part of the query result corresponding to where the fragment is spread becomes a *fragment key* for that fragment. This fragment key is the object that you pass to a component to tell it where in the graph to read the fragment from.

To make this type-safe, Relay generates a type that represents the fragment key for that specific fragment — this way, if you try to use a component without spreading its fragment into your query, you won’t be able to provide a fragment key that satisfies the type system. Here are the changes we need to make:

```
// change-line
import type {StoryFragment$key} from './__generated__/StoryFragment.graphql';

type Props = {
  // change-line
  story: StoryFragment$key;
};
```

With that done, we have a `Newsfeed` that no longer has to care what data `Story` requires, yet can still fetch that data up-front within its own query.

* * *

## Exercise

The `PosterByline` component used by `Story` renders the poster’s name and profile picture. Use these same steps to fragmentize `PosterByline`. You need to:

* Declare a `PosterBylineFragment` on `Actor` and specify the fields it needs (`name`, `profilePicture`). The `Actor` type represents a person or organization that can post a story.
* Spread that fragment within `poster` in `StoryFragment`.
* Call `useFragment` to retrieve the data.
* Update the Props to accept a `PosterBylineFragment$key` as the `poster` prop.

It’s worth going through these steps a second time, to get the mechanics of using fragments under your fingers. There are a lot of parts here that need to slot together in the right way.

Once you’ve done that, let’s look at a basic example of how fragments help an app to scale.

* * *

## Reusing a Fragment in Multiple Places

A fragment says, given *some* graph node of a particular type, what data to read from that node. The fragment key specifies *which node* in the graph the data is selected from. A re-usable component that specifies a fragment can retrieve the data from different parts of the graph in different contexts, by being passed a different fragment key.

For example, notice that the `Image` component is used in two places: directly within `Story` for the story’s thumbnail image, and also within `PosterByline` for the poster’s profile pic. Let’s fragmentize `Image` and see how it can select the data it needs from different places in the graph according to where it is used.



### Step 1 — Define the fragment

Open up `Image.tsx` and add a Fragment definition:

```
import { graphql } from 'relay-runtime';

const ImageFragment = graphql`
  fragment ImageFragment on Image {
    url
  }
`;
```

### Step 2 — Spread the fragment

Go back to `StoryFragment` and `PosterBylineFragment` and spread `ImageFragment` into it in each place where the `Image` component is what’s using the data:

<Tabs>
  <TabItem value="1" label="Story.tsx" default>

```
const StoryFragment = graphql`
  fragment StoryFragment on Story {
    title
    summary
    postedAt
    poster {
      ...PosterBylineFragment
    }
    thumbnail {
      // change-line
      ...ImageFragment
    }
  }
`;
```

  </TabItem>
  <TabItem value="2" label="PosterByline.tsx">

```
const PosterBylineFragment = graphql`
  fragment PosterBylineFragment on Actor {
    name
    profilePicture {
      // change-line
      ...ImageFragment
    }
  }
`;
```

  </TabItem>
</Tabs>

### Step 3 — Call useFragment

Modify the `Image` component to read the fields using its fragment, and also modify its Props to accept the fragment key:

```
import { useFragment } from 'react-relay';
import type { ImageFragment$key } from "./__generated__/ImageFragment.graphql";

type Props = {
  image: ImageFragment$key;
  ...
};

function Image({image}: Props) {
  const data = useFragment(ImageFragment, image);
  return <img key={data.url} src={data.url} ... />
}
```

### Step 4 — Modify once, enjoy everywhere

Now that we’ve fragmentized Image’s data requirements and co-located them within the component, we can add new data dependencies to Image without modifying any of the components that use it.

For example, let’s add an `altText` label for accessibility to the `Image` component.

Edit `ImageFragment` as follows:

```
const ImageFragment = graphql`
  fragment ImageFragment on Image {
    url
    // change-line
    altText
  }
`;
```

Now, without editing Story, Newsfeed, or any other component, all of the images within our query will have alt text fetched for them. So we just need to modify `Image` to use the new field:

```
function Image({image}) {
  // ...
  <img
    // change-line
    alt={data.altText}
  //...
}
```

Now *both* the story thumbnail image and the poster’s profile pic will have an alt text. (You can use your browser’s Elements inspector to verify this.)

You can imagine how beneficial this is as your codebase gets larger. Each component is self-contained, no matter how many places it’s used in! Even if a component is used in hundreds of places, you can add or remove fields from its data dependencies at will. This is one of the main ways that Relay helps you scale with the size of your app.



Fragments are the building blocks of Relay apps. As such, a lot of Relay features are based on fragments. We’ll look at a few of them in the next sections.

* * *

## Fragment arguments and field arguments

Currently the `Image` component fetches images at their full size, even if they’ll be displayed at a smaller size. This is inefficient! The `Image` component takes a prop that says what size to show the image at, so it’s controlled by the component that uses `Image`. We’d like in a similar way for the component that uses `Image` to say what size of image to fetch within its fragment.

GraphQL fields can accept *arguments* that give the server additional information to fulfill our request. For example, the `url` field on the `Image` type accepts `height` and `width` arguments that the server incorporates into the URL — if we have this fragment:

```
fragment Example1 on Image {
  url
}
```

we might get the URL such as `/images/abcde.jpeg`

— whereas if we have this fragment:

```
fragment Example2 on Image {
  url(height: 100, width: 100)
}
```

we might get a URL like `/images/abcde.jpeg?height=100&width=100`

Now of course, we don’t want to just hard-code a specific size into `ImageFragment`, because we’d like the `Image` component to fetch a different size in different contexts.  To do that, we can make the `ImageFragment` accept *fragment arguments* so that the parent component can specify how large of an image should be fetched. These *fragment arguments* can then be passed into specific fields (in this case `url`) as *field arguments*.

To do that, edit `ImageFragment` as follows:

```
const ImageFragment = graphql`
  fragment ImageFragment on Image
    @argumentDefinitions(
      // color1
      width: {
        // color2
        type: "Int",
        // color3
        defaultValue: null
      }
      height: {
        type: "Int",
        defaultValue: null
      }
    )
  {
    url(
      // color4
      width: $width,
      // color4
      height: $height
    )
    altText
  }
`;
```

Let’s break this down:

* We’ve added an `@argumentDefinitions` directive to the fragment declaration. This says what arguments the fragment accepts. For each argument, we give:
    * <span className="color1">The name of the argument</span>
    * <span className="color2">Its type</span> (which can be any <a href="https://graphql.org/learn/schema/#scalar-types">GraphQL scalar type</a>)
    * Optionally a <span className="color3">default value </span>— in this case, the default value is null, which lets us fetch the image at its inherent size. If no default value is given, then the argument is required at every place the fragment is used.
* Then we populate an <span className="color4">argument to a GraphQL field</span> by using the fragment argument as a variable. Here the field arguments and fragment arguments have the same name (as will often be the case), but note: `width:` is the field argument while `$width` is the variable created by the fragment argument.

Now the fragment accepts an argument that it passes along to the server via one of the fields it selects.

<details>

<summary>Deep dive: GraphQL Directives</summary>

The syntax for fragment arguments may look rather clumsy. This is because it is based on *directives*, a system for extending the GraphQL language. In GraphQL, any symbol starting with `@` is a directive. Their meaning isn't defined by the GraphQL spec, but is up to the specific client or server implementation.

Relay defines [several directives](../../api-reference/graphql-and-directives) to support its features — fragment arguments for one. These directives are not sent to the server, but give instructions to the Relay compiler at build time.

The GraphQL spec actually does define the meaning of three directives:

* `@deprecated` is used in schema definitions and marks a field as deprecated.
* `@include` and `@skip` can be used to make the inclusion of a field conditional.

Besides these, GraphQL servers can specify additional directives as part of their schemas. And Relay has its own build-time directives, which allow us to extend the language a bit without changing its grammar.

</details>

***

Now the different fragments using `Image` can pass in the appropriate size for each image:

<Tabs>
  <TabItem value="1" label="Story.tsx" default>

```
const StoryFragment = graphql`
  fragment StoryFragment on Story {
    title
    summary
    postedAt
    poster {
      ...PosterBylineFragment
    }
    thumbnail {
      // change-line
      ...ImageFragment @arguments(width: 400)
    }
  }
`;
```

  </TabItem>
  <TabItem value="2" label="PosterByline.tsx">

```
const PosterBylineFragment = graphql`
  fragment PosterBylineFragment on Actor {
    name
    profilePicture {
      // change-line
      ...ImageFragment @arguments(width: 60, height: 60)
    }
  }
`;
```

  </TabItem>
</Tabs>

Now if you look at the images that our app downloads, you’ll see they’re of the smaller size, saving network bandwidth. Note that although we used integer literals for the value of our fragment arguments, we can also use variables supplied at runtime, as we'll see in later sections.

Field arguments (e.g. `url(height: 100)`) are a feature of GraphQL itself, while fragment arguments (as in `@argumentDefinitions` and `@arguments`) are Relay-specific features. The Relay compiler processes these fragment arguments when it combines fragments into queries.

---

## Summary

Fragments are the most distinctive aspect of how Relay uses GraphQL. We recommend that every component that displays data and cares about the semantics of that data (so not just a typographic or formatting component) use a GraphQL fragment to declare its data dependencies.

* Fragments help you scale: No matter how many places a component is used, you can update its data dependencies in a single place.
* Fragment data needs to be read out with `useFragment`.
* `useFragment` takes a *fragment key* which says where in the graph to read from.
* Fragment keys come from places in a GraphQL response where that fragment was spread.
* Fragments can define arguments which are used at the point they’re spread. This allows them to be tailored to each situation they're used in.

We'll be revisiting many other features of fragments, such as how to refetch the contents of a single fragment without refetching the entire query. First, though, let's make this newsfeed app more newsfeed-like by learning about arrays.

---

### Tutorial Graphql (`website/docs/tutorial/graphql.mdx`)

# GraphQL and Relay

This section is an overview to situate Relay in relation to GraphQL, React, and the other parts of the stack. Don’t worry about understanding every detail, just try to get the gist and then proceed to the next section to start working with code. Much more specifics will be explained as we go through working examples throughout the tutorial.

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

* * *

GraphQL is a language for querying and modifying data on servers. The unique thing about GraphQL is that rather than having a fixed set of API endpoints, your server provides a palette of options that the client can use to request any combination of data that it may need. This allows front-end developers to move more quickly because there is no need to write and deploy new endpoints as data requirements change. It also means that when a new version of the client is released, it can request just the data it needs, without extra fields leftover for compatibility with older versions.

GraphQL provides a unified interface for querying data across any kind of back-end. Whether your data is in a relational SQL database, a graph-oriented database, or an armada of microservices, a GraphQL server can collect the data from multiple back-ends and send it to the client in a single response, which is more efficient than issuing separate queries to each service from the client.

In a traditional HTTP API, there are URLs that each respond with a fixed set of information:

```
Request:
GET /person?id=24601

Response:
{"id": "24601", "name": "Jean Valjean", "age": 64, "occupation": "Mayor"}
```

In GraphQL, the client asks for the specific information that it wants, and the server responds with just the information that was requested:

```
Request:
query {
  person(id: "24601") {
    name
    occupation
  }
}

Response:
{
  "person": {
    "name": "Jean Valjean",
    "occupation": "Mayor"
  }
}
```

Notice that only the specific fields that the client requested were included in the response.

As the name suggests, GraphQL organizes data into a *graph*. The graph consists of *nodes* (like objects or records) and *edges* (pointers from one node to another):



GraphQL lets you follow those edges from one node to another and ask for information about each node that you visit. For example, here we go from a person to their city and get information about the city:

<Tabs>
  <TabItem value="1" label="Request" default>

```
query {
  person(id: "24601") {
    name
    occupation
    location {
      name
      population
    }
  }
}
```



  </TabItem>
  <TabItem value="2" label="Response">

```
{
  "person": {
    "name": "Jean Valjean",
    "occupation": "Mayor",
    "location": {
      "name": "Montreuil-sur-Mer",
      "population": 1935
    }
  }
}
```



  </TabItem>
</Tabs>

This means we can retrieve information about a whole panoply of objects all in one query — in other words, you can efficiently get all the data for a screen in a single request instead of sending many requests one after the other. But you achieve this without writing and maintaining a separate endpoint for each screen in your UI.

Instead, your GraphQL server provides a *schema*, which describes what kinds of nodes there are, how they’re connected, and what information each node contains. Then, you pick and choose from this schema to select the information you want.

The example app in this tutorial is a newsfeed app, so its schema consists of types such as

* `Story`, which represents a newsfeed story — it has fields such as its title, an image, and an *edge* to the person or organization who posted it
* `Person`, with information such as their name, email, and a list of friends (which are edges to other Persons).
* `Viewer`, which represents the person viewing the app and has information like their list of newsfeed stories
* `Image`, which has a URL for the image itself as well as an `alt` text description.

The GraphQL language includes a type system and language for specifying the schema. Here’s a snippet from the schema definition for our example app — don’t worry about every detail, it’s just to give you a general idea:

```
// A newsfeed story. It has fields, some of which are scalars (e.g. strings
// and numbers) and some that are edges that point to other nodes in the graph,
// such as the 'thumbnail' and 'poster' fields:
type Story {
  id: ID!
  category: Category
  title: String
  summary: String
  thumbnail: Image
  poster: Actor
}

// An Actor is an entity that can do something on the site. This is an
// interface that multiple different types can implement, in this case
// Person and Organization:
interface Actor {
  id: ID!
  name: String
  profilePicture: Image
}

// This is a specific type that implements that interface:
type Person implements Actor {
  id: ID!
  name: String
  email: String
  profilePicture: Image
  location: Location
}

// The schema also lets you define enums, such as the category
// of a newsfeed story:
enum Category {
  EDUCATION
  NEWS
  COOKING
}
```

Besides queries, GraphQL also lets you send *mutations* that ask the server to update its data. If queries are analogous to HTTP GET requests, then mutations are the equivalent of POST requests. Like POSTs, they let the server respond with updated data. GraphQL also has *subscriptions* which allow for an open connection for realtime updates.

(GraphQL is usually implemented over HTTP, so queries and mutations are not only *analogous* to GET and POST, but may be sent as such as well.)

* * *

Now that we’ve talked about GraphQL, let’s talk about Relay. It has a few different parts and pieces that we’ll briefly go over before diving into the code.

Relay is a data management library for the client that’s oriented around GraphQL, but uses it in a very specific way that gets the most benefit from it.

For the best performance, you want your app to issue a single request at the beginning of each screen or page instead of having individual components issue their own requests. But the problem with that is that it couples components and screens together, creating a big maintenance problem: If you need some additional data in a specific component, you have to find every screen where that component is used and add the new field to that screen’s query. On the other hand, if you remove the need for a particular field, you have to remove that field from every query again — but this time, are you sure the field isn’t still in use by some *other* component? It becomes very difficult to maintain these big screen-wide queries.

Relay’s unique strength is to avoid this tradeoff by letting each component declare its own data requirements locally, but then stitching those requirements together into larger queries. That way you get both performance and maintainability.

Relay does this with a *compiler* that scans your JavaScript code for fragments of GraphQL, and then stitches those fragments together into complete queries.



Besides the compiler, Relay has runtime code that manages the fetching and processing of GraphQL. It maintains a local cache of all the data that has been retrieved (called the *Store*), and vends out to each component the data that belongs to it:



The advantage of having a centralized Store is that it lets you keep your data consistent when it’s updated. For instance, if your UI has a way for somebody to edit their name, then you can make that update in a single place and every component that displays that person’s name will see the new information, even if they’re on different screens and therefore used different queries to initially retrieve the data. This is because Relay *normalizes* the data as it comes in, meaning that it merges all the data it sees for a single graph node into one place, so it doesn’t have multiple copies of the same node.

Indeed, Relay doesn’t just query data, it provides functions to manage the entire lifecycle of querying and updating, including support for optimistic updates and rollbacks. You can paginate, refresh data — all of the basic operations you’ll need to create a UI. Whenever data in the Store is updated, Relay efficiently re-renders just those components that are displaying that particular data.

## Summary

GraphQL is a language for modeling data as a graph and querying that data from a server (as well as updating the data). Relay is a React-based client library for GraphQL that lets you build up queries from individual fragments that are co-located with each React component. Once the data has been queried, Relay maintains consistency and re-renders components as the data is updated.

---

### Tutorial Interfaces Polymorphism (`website/docs/tutorial/interfaces-polymorphism.mdx`)

# GraphQL Types, Interfaces, and Polymorphism

In this section, we’ll see how to treat different types of nodes differently. You might notice that some of the newsfeed stories in the example app are posted by people, while others are posted by organizations. In this example, we'll enhance our hovercard by writing a fragment that selects people-specific information about people  and organization-specific information about organizations.

* * *

We’ve alluded to the fact that GraphQL nodes aren’t just random bags of fields — they have types. Your GraphQL schema defines what fields each type has. For instance, it might define the `Story` type like this:

```
type Story {
  id: ID!
  title: String
  summary: String
  createdAt: Date
  poster: Actor
  image: Image
}
```

Here, some of the fields are scalars (like `String` and `ID`). Others are types defined elsewhere in the schema, like `Image` — these fields are edges to nodes of those specific types. The `!` on `ID!` means that field is non-nullable. In GraphQL, fields are normally nullable and non-nullability is the exception.

Fragments are always “on” a particular type. In our example above, `StoryFragment` is defined `on Story`. This means that you can only spread it into places in a query where a `Story` node is expected. And it means that the fragment can select just those fields that exist on the `Story` type.

Of particular interest is the `Actor` type used for the `poster` field. This type is an *interface*. That means that the `poster` of a story can be a Person, a Page, an Organization, or any other type of entity that meets the specifications for being an “Actor”.

The GraphQL schema in our example app defines an Actor as follows:

```
interface Actor {
  name: String
  profilePicture: Image
  joined: DateTime
}
```

Not coincidentally this is exactly the information that we’re displaying here. There are two types in the schema that *implement* Actor, meaning that they include all the fields defined in Actor. They are declared as such:

```
type Person implements Actor {
  id: ID!
  name: String
  profilePicture: Image
  joined: DateTime
  email: String
  location: Location
}

type Organization implements Actor {
  id: ID!
  name: String
  profilePicture: Image
  joined: DateTime
  organizationKind: OrganizationKind
}
```

Both of these types have `name` , `profilePicture`, and `joined`, so they can both declare that they implement Actor and thus can be used wherever an Actor is called for in the schema and in fragments. They also have other fields that are distinct to each particular type.

Let’s see how to work with interfaces more by extending the `PosterDetailsHovercardContentsBody` component to display the location of a `Person` or the organization kind of an `Organization`. These are fields that are only present on those specific types, not on the `Actor` interface.

Right now, if you’ve followed along so far, it should have a fragment defined like this (in `PosterDetailsHovercardContents.tsx`):

```
fragment PosterDetailsHovercardContentsBodyFragment on Actor {
  name
  joined
  profilePicture {
    ...ImageFragment
  }
}
```

If you try to add a field like `organizationKind` to this fragment, you’ll get an error from the Relay compiler:

```
✖︎ The type `Actor` has no field organizationKind
```

This is because when we define a fragment as being on an interface, we can only use fields from that interface. To use fields from a specific type that implements the interface, we use a *type refinement* to tell GraphQL we’re selecting fields from that type:

```
fragment PosterDetailsHovercardContentsBodyFragment on Actor {
  name
  joined
  profilePicture {
    ...ImageFragment
  }
  // change
  ... on Organization {
    organizationKind
  }
  // end-change
}
```

Go ahead and add this now. You can also add a type refinement for `Person`:

```
fragment PosterDetailsHovercardContentsBodyFragment on Actor {
  name
  joined
  profilePicture {
    ...ImageFragment
  }
  ... on Organization {
    organizationKind
  }
  // change
  ... on Person {
    location {
      name
    }
  }
  // end-change
}
```

When you select a field that’s only present on some of the types that implement an interface, and the node you’re dealing with is of a different type, then you simply get `null` for the value of that field when you read it out. With that in mind, we can modify the `PosterDetailsHovercardContentsBody` component to show the location of people and organization kind of organizations:

```
import OrganizationKind from './OrganizationKind';

function PosterDetailsHovercardContentsBody({ poster }: Props): React.ReactElement {
  const data = useFragment(PosterDetailsHovercardContentsBodyFragment, poster);
  return (
    <>
      <Image image={data.profilePicture} width={128} height={128} className="posterHovercard__image" />
      <div className="posterHovercard__name">{data.name}</div>
      <ul className="posterHovercard__details">
         <li>Joined <Timestamp time={poster.joined} /></li>
         // change
         {data.location != null && (
           <li>{data.location.name}</li>
         )}
        {data.organizationKind != null && (
          <li><OrganizationKind kind={data.organizationKind} /></li>
         )}
         // end-change
      </ul>
    </>
  );
}
```

You should now see the location of people, and the organization kind for organizations:

 

By the way, we can now understand why we had `... on Actor` in the example earlier. The `node` field can return a node of any type because any ID could be given at runtime. So the type that it gives us is `Node`, a very generic interface that can be implemented by anything that has an `id` field. We needed a type refinement to use fields from the `Actor` interface.

:::note
In the GraphQL spec and other sources, type refinements are called *inline fragments*. We call them “type refinements” instead because this terminology is more descriptive and less confusing.
:::

:::tip
If you need to do something totally different depending on what type it is, you can select a field called `__typename`, which returns a string with the name of the concrete type that you got (e.g., `"Person"` or `"Organization"`). This is a built-in feature of GraphQL.
:::

## Summary

The `... on Type {}` syntax allows us to select fields that are only present in a specific type that implements an interface.

---

### Tutorial Mutations Updates (`website/docs/tutorial/mutations-updates.mdx`)

# Mutations & Updates

In this chapter we’ll learn how to update data on the server and client. We’ll go through two main examples:

* Implementing a Like button for newsfeed stories
* Implementing the ability to post comments on a newsfeed story

Updating data is a complicated problem domain, and Relay handles many aspects of it automatically, while also giving you a lot of manual control so that your app can be as robust as possible in handling the cases that can arise.

First let’s distinguish two terms:

* A *mutation* is when you ask the server to perform some action that modifies data on the server. This is a feature of GraphQL that is analogous to an HTTP POST.
* An *update* is when you modify Relay’s local client-side data store.

The client doesn’t have the ability to directly manipulate individual pieces of data on the server side. Rather, mutations are opaque, high-level requests that express the user’s intent — for example, that the user friended somebody, joined a group, posted a comment, liked a particular newsfeed story, blocked somebody, or deleted a comment. (The GraphQL schema defines what mutations are available, as well as the input parameters that each mutation accepts.)

Mutations can have far-reaching and unpredictable effects on the state of the graph. For example, let’s say you join a group. Many things can change:

* Your name gets added to the Group Members list
* The group’s membership count gets incremented
* The group gets added to your list of groups
* Members-only posts appear in the group’s post feed
* Your recommended groups may change
* The group’s admins may get notifications
* Many other non-user-visible effects such as logging, training models, or sending emails
* Etc. etc. etc.

In general, it’s impossible to know what the full downstream effect of a mutation may be. So after asking the server to perform a mutation, the client just has to do its best to update its local data store, keeping the data as consistent as reasonably possible. It does this by asking the server for specific updated data as part of the mutation response, and by imperative code — called an *updater* — that fixes up the store to keep it consistent.

There is no principled solution that covers every case. Even if it were possible to know the full effect of a mutation on the graph, there are even circumstances where we don’t *want* to show updated data right away. For example, if you go to somebody’s profile page and block them, you don’t want for everything shown on that page to immediately disappear. The question of what data to update is ultimately a UI design decision.

Relay tries to make it as easy as possible to update data in response to a mutation. For example, if you want to update a certain component, you can spread its fragment into your mutation, which asks the server to send updated data for whatever was selected by that fragment.  For other cases, you have to manually write an *updater* that modifies Relay’s local data store imperatively. We’ll look at all of these cases below.
* * *

## Implementing a Like Button

Let’s dip our toes in the water by implementing the Like button for Newsfeed stories. Luckily we already have a Like button prepared, so open up `Story.tsx` and drop it in to the `Story` component, remembering to spread its fragment into Story’s fragment:

```
// change-line
import StoryLikeButton from './StoryLikeButton';

...

const StoryFragment = graphql`
  fragment StoryFragment on Story {
    title
    summary
    // ... etc
    // change-line
    ...StoryLikeButtonFragment
  }
`;

...

export default function Story({story}: Props) {
  const data = useFragment(StoryFragment, story);
  return (
    <Card>
      <PosterByline person={data.poster} />
      <Heading>{data.title}</Heading>
      <Timestamp time={data.posterAt} />
      <Image image={story.thumbnail} width={400} height={400} />
      <StorySummary summary={data.summary} />
      // change-line
      <StoryLikeButton story={data} />
      <StoryCommentsSection story={data} />
    </Card>
  );
}
```

Now let’s take a look at `StoryLikeButton.tsx`. Currently, it is a button that doesn’t do anything, along with a like count.



You can look at its fragment to see that it fetches a field `likeCount` for the like count and `doesViewerLike` to determine whether the Like button is highlighted (it’s highlighted if the viewer likes the story, i.e. if `doesViewerLike` is true):

```
const StoryLikeButtonFragment = graphql`
  fragment StoryLikeButtonFragment on Story {
    id
    likeCount
    doesViewerLike
  }
`;
```

We want to make it so that when you press the Like button

1. The story gets “liked” on the server
2. Our local client copy of the “`likeCount`” and “`doesViewerLike`” fields get updated.

To do that, we need to write a GraphQL mutation. But first...

## Anatomy of a Mutation

The GraphQL mutation syntax is going to be confusing unless you first understand the following:

GraphQL has two different request types, Queries and Mutations — and they work in exactly the same way. This is analogous to how HTTP has GET and POST: technically the only difference is that POST requests are intended to cause effects while GET requests do not. Similarly, a Mutation is exactly like a Query, except that the Mutation is expected to cause things to happen. This means:

* A mutation is part of our client code
* A mutation declares *variables* that let the client pass data to the server
* The server implements *individual fields.* A given mutation composes together those fields and passes its variables in as field arguments.
* Each field yields data of a particular type — either scalar or an edge to some other graph node — which is returned to the client if that field is selected. In the case of edges, further fields are selected from the node being linked to.

The only difference is that, in a mutation, selecting a field makes something happen, as well as returning data.

## The Like Mutation

With that in mind, this is what our mutation is going to look like — go ahead and add this declaration to the file:

```
const StoryLikeButtonLikeMutation = graphql`
  mutation StoryLikeButtonLikeMutation(
    // color1
    $id: ID!,
    // color1
    $doesLike: Boolean!,
  ) {
    // color2
    likeStory(
      // color3
      id: $id,
      // color3
      doesLike: $doesLike
    ) {
      // color4
      story {
        // color5
        id
        // color5
        likeCount
        // color5
        doesViewerLike
      }
    }
  }
`;
```

This is a lot, let’s break it down:

* The mutation is named `StoryLikeButton` + `Like` + `Mutation` because it must begin with the module name, and end with the GraphQL operation.
* The mutation declares <span className="color1">variables</span> which are passed from the client to the server when the mutation is dispatched. Each variable has a name (`$id`, `$doesLike`) and a type (`ID!`, `Boolean!`). The `!` after the type indicates that it is required, not optional.
* The mutation selects a <span className="color2">mutation field</span> defined by the GraphQL schema. Each mutation field that the server defines corresponds to some action that the client can request of the server, such as liking a story.
    * The <span className="color3">mutation field takes arguments</span> (just like any field can do). Here we pass in the mutation variables that we declared as the argument values — for example, the `doesLike` field argument is set to be the `$doesLike` mutation variable.
* The `likeStory` field returns an edge to a node that represents the mutation response. We can select various fields in order to receive updated data. The fields that are available in the mutation response are specified by the GraphQL schema.
    * We select the `story` field, which is an <span className="color4">edge to the Story that we just liked</span>.
    * We select specific <span className="color5">fields from within that Story to get updated data</span>. These are the same fields that a query could select about a Story — in fact, the same fields we selected in our fragment.

When we send the server this mutation, we’ll get a response that, just like with queries, matches the shape of the mutation that we sent. For example, the server might send this back to us:

```
{
  "likeStory": {
    "story": {
      "id": "34a8c",
      "likeCount": 47,
      "doesViewerLike": true
    }
  }
}
```

and our job will be to update the local data store to incorporate this updated information. Relay will handle this in simple cases, while in more complex cases it will require custom code to update the store intelligently.

But we’re getting ahead of ourselves — let’s make that button trigger the mutation. Here’s what our component looks like now — we need to hook up the `onLikeButtonClicked` event to execute `StoryLikeButtonLikeMutation`.

```
function StoryLikeButton({story}) {
  const data = useFragment(StoryLikeButtonFragment, story);
  function onLikeButtonClicked() {
    // To be filled in
  }
  return (
    <>
      <LikeCount count={data.likeCount} />
      <LikeButton value={data.doesViewerLike} onChange={onLikeButtonClicked} />
    </>
  )
}
```

To do that, we add a call to `useMutation`:

```
// change-line
import {useMutation, useFragment} from 'react-relay';

function StoryLikeButton({story}) {
  const data = useFragment(StoryLikeButtonFragment, story);
  // change-line
  const [commitMutation, isMutationInFlight] = useMutation(StoryLikeButtonLikeMutation);
  function onLikeButtonClicked() {
    // change
    commitMutation({
      variables: {
        id: data.id,
        doesLike: !data.doesViewerLike,
      },
    })
    // end-change
  }
  return (
    <>
      <LikeCount count={data.likeCount} />
      <LikeButton value={data.doesViewerLike} onChange={onLikeButtonClicked} />
    </>
  )
}
```

The `useMutation` hook returns a function `commitMutation` that we can call to tell the server to do stuff.

We pass in an option called `variables` where we give values for the variables defined by the mutation, namely `id` and `doesViewerLike`. This tells the server which story we’re talking about and whether the we are liking or un-liking it. The `id` of the story we’ve read from the fragment, while whether we like it or unlike it comes from toggling whatever the current value that we rendered is.

The hook also returns a boolean flag that tells us when the mutation is in flight. We can use that to make the user experience nicer by disabling the button while the mutation is happening:

```
<LikeButton
  value={data.doesViewerLike}
  onChange={onLikeButtonClicked}
  // change-line
  disabled={isMutationInFlight}
/>
```

With this in place, we should now be able to like a story!

## How Relay Automatically Processes Mutation Responses

But how did Relay know to update the story we clicked on? The server sent back a response with this form:

```
{
  "likeStory": {
    "story": {
      "id": "34a8c",
      "likeCount": 47,
      "doesViewerLike": true
    }
  }
}
```

Whenever the response includes an object with an `id` field, Relay will check if the store already contains a record with a matching ID in the `id` field of that record. If there is a match, Relay will merge the other fields from the response into the existing record. That means that, in this simple case, we don’t need to write any code to update the store.
* * *

## Using Fragments in the Mutation Response

Remember that mutations are just like queries. In order to make sure that the mutation response always contains the data we want to render, instead of having a separate set of fields that has to be manually kept up to date, we can simply spread fragments into our mutation response:

```
const StoryLikeButtonLikeMutation = graphql`
  mutation StoryLikeButtonLikeMutation(
    $id: ID,
    $doesLike: Boolean,
  ) {
    likeStory(id: $id, doesLike: $doesLike) {
      story {
        // change-line
        ...StoryLikeButtonFragment
      }
    }
  }
`;
```

Now if we add or remove data requirements, all of the necessary data (but no more) will be included with the mutation response. This is usually the smart way of writing mutation responses. You can spread in any fragment from any component, not just the component that triggers the mutation. This helps you keep your whole UI up to date.
* * *

## Improving the UX with an Optimistic Updater

Mutations take time to perform, yet we always want the UI to update immediately in some way to give the user feedback that they’ve taken an action. In the current example, the Like button is disabled while the mutation is happening, and then after the mutation is done, the UI is updated into the new state as Relay merges the updated data into its store and re-renders the affected components.

Oftentimes the best feedback will be to simply pretend the operation is already completed: for example, if you press the Like button, that buttons immediately goes into the same highlighted state that it will stay in whenever you see something you’ve already liked. Or take the example of posting a comment: We would like to immediately show your comment as having been posted. This is because mutations are usually fast and reliable enough that we don’t need to bother the user with a separate loading state for them. However, sometimes mutations do end in failure. In that case, we’d like to roll back the changes we made and return you to the state you were in before we tried the mutation: the comment we showed as being posted should go away, while the text of the comment should re-appear within the composer where you wrote it, so that the data isn’t lost if you want to try posting again.

Managing these so-called *optimistic updates* is complicated to do manually, but Relay has a robust system for applying and rolling back updates. You can even have multiple mutations in flight at the same time (say if the user clicks several buttons in sequence), and Relay will keep track of what changes need to be rolled back in case of a failure.

Mutations proceed in three phases:

* First there’s an *optimistic update*, where you update the local data store into whatever state you anticipate and want to show to the user immediately.
* Then you actually perform the mutation on the server. If it’s successful, the server responds with updated information which can be used in the third step.
* When the mutation is done, you roll back the optimistic update. If the mutation failed, you’re done — back to where you started. If the mutation succeeded, Relay merges simple changes into the store and then applies a *concluding update* that updates the local data store with the actual new information received from the server, plus whatever other changes you want to make.



* * *
With this background knowledge in hand, let’s go ahead and write an optimistic updater for our Like button so that it immediately updates to the new state when clicked.

### Step 1 — Add the optimisticUpdater option to commitMutation

Go to `StoryLikeButton` and add a new option to the call to `commitMutation`:

```
function StoryLikeButton({story}) {
  ...
  function onLikeButtonClicked(newDoesLike) {
    commitMutation({
      variables: {
        id: data.id,
        doesLike: newDoesLike,
      },
      // change
      optimisticUpdater: store => {
        // TODO fill in optimistic updater
      },
      // end-change
    })
  }
  ...
}
```

This callback receives a `store` argument which represents Relay’s local data store. It has various methods for reading and writing local data. All of the writes that we make in the optimistic updater will be applied immediately when the mutation is dispatched, and then rolled back when it is complete.

### Step 2 — Create an Updatable Fragment

We can read and write data in the local store by writing a special kind of fragment called an *updatable fragment.* Unlike a regular fragment, it doesn’t get spread into queries and sent to the server. Instead, it lets us read data out of the local store using the same GraphQL syntax we already know and love. Go ahead and add this fragment definition:

```
function StoryLikeButton({story}) {
  ...
      optimisticUpdater: store => {
        const fragment = graphql`
          fragment StoryLikeButton_updatable on Story
            // color1
            @updatable
          {
            likeCount
            doesViewerLike
          }
        `;
      },
  ...
}
```

It’s exactly like any other fragment but annotated with the <span className="color1">@updatable</span> directive.

Unlike normal fragments, updatable fragments are not spread into queries and do not select data to be fetched from the server. Instead, they select data that’s already in the Relay local data store so that the data may be updated.

### Step 3 — Call readUpdatableFragment

We pass this <span className="color2">fragment</span>, along with the <span className="color3">original fragment ref</span> that we received as a prop (which tells us *which* story we’re liking), to `store.readUpdatableFragment`. It returns a <span className="color1">special object called `updatableData`</span>:

```
function StoryLikeButton({story}) {
  ...
      optimisticUpdater: store => {
        const fragment = graphql`
          fragment StoryLikeButton_updatable on Story @updatable {
            likeCount
            doesViewerLike
          }
        `;
        const {
          // color1
          updatableData
        } = store.readUpdatableFragment<StoryLikeButton_updatable$key>(
          // color2
          fragment,
          // color3
          story
        );
      },
  ...
}
```

### Step 4 — Modify the Updatable Data

Now `updatableData` is an object representing our existing Story as it exists in the local store. We can read and write the fields listed in our fragment:

```
function StoryLikeButton({story}) {
  ...
      optimisticUpdater: store => {
        const fragment = graphql`
          fragment StoryLikeButton_updatable on Story @updatable {
            likeCount
            doesViewerLike
          }
        `;
        const { updatableData } =
          store.readUpdatableFragment<StoryLikeButton_updatable$key>(
            fragment,
            story
          );
        // change
        const alreadyLikes = updatableData.doesViewerLike;
        updatableData.doesViewerLike = !alreadyLikes;
        updatableData.likeCount += (alreadyLikes ? -1 : 1);
        // end-change
      },
  ...
}
```

In this example, we toggle `doesViewerLike` (so that clicking the button when you already like the story makes you un-like it) and increment or decrement the like count accordingly.

Relay records the changes we made to `updatableData` and will roll them back once the mutation is complete.

Now when you click the Like button, you should see the UI immediately update.

* * *

## Adding Comments — Mutations on Connections

The only thing that Relay can do completely automatically is what we’ve seen already: merge nodes in the mutation response with existing nodes that share the same ID in the store. For anything else, we have to give Relay some more information.

Let’s look at the case of Connections. We’ll implement the ability to post a new comment on a story.

The server’s mutation response only includes the newly-created comment. We have to tell Relay how to insert that story into the Connection between a story and its comments.

Head back over to `StoryCommentsSection` and add a component for posting a new comment, remembering to spread its fragment into our fragment:

```
// change-line
import StoryCommentsComposer from './StoryCommentsComposer';

const StoryCommentsSectionFragment = graphql`
  fragment StoryCommentsSectionFragment on Story
    ...
  {
    comments(after: $cursor, first: $count)
      @connection(key: "StoryCommentsSectionFragment_comments")
    {
      ...
    }
    // change-line
    ...StoryCommentsComposerFragment
  }
`

function StoryCommentsSection({story}) {
  ...
  return (
    <>
      // change-line
      <StoryCommentsComposer story={data} />
      ...
    </>
  );
}
```

We should now see a composer at the top of the comments section:



Now take a look inside `StoryCommentsComposer.tsx`:

```
function StoryCommentsComposer({story}) {
  const data = useFragment(StoryCommentsComposerFragment, story);
  const [text, setText] = useState('');
  function onPost() {
   // TODO post the comment here
  }
  return (
    <div className="commentsComposer">
      <TextComposer text={text} onChange={setText} onReturn={onPost} />
      <PostButton onClick={onPost} />
    </div>
  );
}
```

### Step 1 — Define the Comment Posting Mutation

Just like before, we need to define a mutation. It will send to the server the story ID and the text of the comment to be added:

```
const StoryCommentsComposerPostMutation = graphql`
  mutation StoryCommentsComposerPostMutation(
    $id: ID!,
    $text: String!,
  ) {
    postStoryComment(id: $id, text: $text) {
      commentEdge {
        node {
          id
          text
        }
      }
    }
  }
`;
```

Here, the schema allows us to select as part of the mutation response the newly-created edge to the newly-created comment. We select it and will use it to update the local store by inserting this edge into the Connection.

### Step 2 — Call commitMutation to post it

Now we use the `useMutation` hook to get access to the `commitMutation` callback, and call it in `onPost`:

```
function StoryCommentsComposer({story}) {
  const data = useFragment(StoryCommentsComposerFragment, story);
  const [text, setText] = useState('');
  // change-line
  const [commitMutation, isMutationInFlight] = useMutation(StoryCommentsComposerPostMutation);
  function onPost() {
    // change
    setText(''); // Reset the UI
    commitMutation({
      variables: {
        id: data.id,
        text,
      },
    })
    // end-change
  }
  ...
}
```

### Step 3 — Add a Declarative Connection Handler

At this point, we can find from the network logs that clicking Post will send a mutation request to the server — you can even see that the comment has been posted since it appears if you refresh the page. However, nothing happens in the UI. We need to tell Relay to append the newly-created comment to the Connection that goes from the story to its comments.

You’ll notice that in the mutation response that we wrote above we select `commentEdge`. This is the edge to the newly-created comment. We just need to tell Relay what Connections to add that edge to. Relay provides directives called `@appendEdge`, `@prependEdge`, and `@deleteEdge` that you put on the edge in the mutation response. Then when you run the mutation, you pass in the IDs of the Connections that you want to modify. Relay will append, prepend, or delete the edge from those connections as you specify.

We want our newly-created comment to appear at the top of the list, so we’ll use `@prependEdge`. Make the following additions to the mutation definition:

```
  mutation StoryCommentsComposerPostMutation(
    $id: ID!,
    $text: String!,
    // change-line
    $connections: [ID!]!,
  ) {
    postStoryComment(id: $id, text: $text) {
      commentEdge
        // change-line
        @prependEdge(connections: $connections)
      {
        node {
          id
          text
        }
      }
    }
  }
```

We’ve added a variable called `connections` to the mutation. We’ll use this to pass in the Connections we want to update.

:::note
The `$connections` variable is only used as an argument to the `@prependEdge` directive, which is processed on the client by Relay. Because `$connections` is not passed as an argument to any *field*, it is not sent to the server.
:::

### Step 4 — Pass in the Connection ID as a Mutation Variable

We need to identify the Connection to add the new edge to. A Connection is identified with two pieces of information:

* Which node it’s off of — in this case, the Story we’re posting a comment to.
* The *key* provided in the `@connection` directive, which lets us distinguish connections in case more than one connection is off of the same node.

We pass this information in to the mutation variables using a special API provided by Relay:

```
// change-line
import {useFragment, useMutation, ConnectionHandler} from 'react-relay';

...

export default function StoryCommentsComposer({story}: Props) {
  ...
  function onPost() {
    setText('');
    // change
    const connectionID = ConnectionHandler.getConnectionID(
      data.id,
      'StoryCommentsSectionFragment_comments',
    );
    // end-change
    commitMutation({
      variables: {
        id: data.id,
        text,
        // change-line
        connections: [connectionID],
      },
    })
  }
  ...
}
```

The string `"StoryCommentsSectionFragment_comments"` that we pass to `getConnectionID` is the identifier that we used when fetching the connection in `StoryCommentSection` — just as a reminder, here's what that looked like:

```
const StoryCommentsSectionFragment = graphql`
  fragment StoryCommentsSectionFragment on Story
  ...
  {
    comments(after: $cursor, first: $count)
     @connection(key: "StoryCommentsSectionFragment_comments")
    {
      ...
  }
`;
```

Meanwhile, the argument `data.id` is the ID of the specific story that we’re connecting off of.

With this change, we should see the comment appear in the list of comments once the mutation is complete.

* * *

## Summary

Mutations let us ask the server to make changes.

* Just like Queries, Mutations are composed of fields, accept variables, and pass those variables as arguments to fields.
* The fields that are selected by a Mutation constitute the *mutation response* which we can use to update the Store.
* Relay automatically merges nodes in the response to nodes in the Store with matching IDs.
* The `@appendEdge`, `@prependEdge`, and `@deleteEdge` directives let us insert and remove items from the mutation response into Connections in the store.
* Updaters let us manually manipulate the store.
* Optimistic updaters run before the mutation begins and are rolled back when it is done.

---

### Tutorial Organizing Mutations Queries And Subscriptions (`website/docs/tutorial/organizing-mutations-queries-and-subscriptions.mdx`)

# Organizing GraphQL Operations

In Relay, GraphQL operation and fragment names must be globally unique and must end with the GraphQL operation type (e.g. `Query`, `Mutation`, `Subscription`).

### Recommended Organization For Mutations and Subscriptions

Put Mutations in their own hook module so the name is closer to _what the mutation does_ rather than _which component invokes it_. If the module name is correctly descriptive, it is fine to declare it in the same file.

If you are adding a Mutation for `Post`, like adding a comment to a post, you may create a new file titled `useAddPostComment.js`. Your mutation (in this file) will then be named `useAddPostCommentMutation`, which is a perfectly descriptive name.

### Recommended Organization for Queries and Fragments

Root components should have a single query that is tightly coupled to a component, since it describes that component's data dependencies. Queries and fragments should co-locate with their data-use code.

---

### Tutorial Queries 1 (`website/docs/tutorial/queries-1.mdx`)

# Query Basics

In this section:

* We’ll take a React component that displays hard-coded placeholder data and modify it so that it fetches its data using a GraphQL query.
* We’ll learn how to use the TypeScript types that Relay generates from your GraphQL to ensure type safety.

* * *
With Relay, you fetch data using GraphQL Queries. A Query specifies a part of the GraphQL graph for your app to fetch, starting from some root node and traversing from node to node to retrieve a particular set of data in the shape of a tree.



Right now, our example app doesn’t fetch any data, it just renders some placeholder data that’s hard-coded into the React components. Let’s modify it to fetch some data using Relay.

Open up the file called `Newsfeed.tsx`. (All of the components in the tutorial are in `src/components`.) In it you should see a `<Newsfeed>` component where the data is hard-coded:

```jsx
export default function Newsfeed() {
  const story = {
    title: "Placeholder Story",
    summary:
      "Placeholder data, to be replaced with data fetched via GraphQL",
    poster: {
      name: "Placeholder Person",
      profilePicture: {
        url: "/assets/cat_avatar.png",
      },
    },
    thumbnail: {
      url: "/assets/placeholder.jpeg",
    },
  };
  return (
    <div className="newsfeed">
      <Story story={story} />
    </div>
  );
}
```

We’re going to replace this placeholder data with data fetched from the server.  First we need to define a GraphQL query. Add the following declaration above the Newsfeed component:

```
import { graphql } from 'relay-runtime';

// color1
const NewsfeedQuery = graphql`
  // color2
  query NewsfeedQuery {
    topStory {
      // color3
      title
      // color3
      summary
      // color4
      poster {
        name
        profilePicture {
          url
        }
      }
      thumbnail {
        url
      }
    }
  }
`;
```

Let’s break this down:

* To embed GraphQL within JavaScript, we put a string literal <span className="color1">marked with the <code>graphql``</code> tag</span>. This tag allows the Relay compiler to find and compile the GraphQL within a JavaScript codebase.
* Our GraphQL string consists of a <span className="color2">query declaration</span> with the keyword `query` and then a query name. The query name must be globally unique and end with `Query`.
* Inside the query declaration are *fields*, which specify what information to query for*:*
    * Some fields are *<span className="color3">scalar fields</span>* that retrieve a string, number, or other unit of information.
    * Other fields are *<span className="color4">edges</span>* that let us traverse from one node in the graph to another. When a field is an edge, it’s followed by another block `{ }` containing fields for the node at the other end of the edge. Here, the `poster` field is an edge that goes from a Story to a Person who posted it. Once we’ve traversed to the Person, we can include fields about the Person such as their `name`.

This illustrates the part of the graph that this query is asking for:



Now that we’ve defined the query, we need to do two things.
1. Run the Relay compiler so that it knows about the new Graphql query. (`npm run relay`)
2. Modify our React component to fetch it and to use the data returned by the server.

If you open `package.json` you will find the script `relay` is hooked up to run the Relay compiler. This is what `npm run relay` does. Once the compiler successfully updates/generated the new compiled query you will be able to find it in the `__generated__` folder under `src/components/` as `NewsfeedQuery.graphql.ts`.

Next, turn back to the `Newsfeed` component and start by deleting the placeholder data. Then, replace it with this:

```
import { useLazyLoadQuery } from "react-relay";

export default function Newsfeed({}) {
  const data = useLazyLoadQuery(
    // color1
    NewsfeedQuery,
    // color2
    {},
  );
  const story = data.topStory;
  // As before:
  return (
    <div className="newsfeed">
      <Story story={story} />
    </div>
  );
}
```

The `useLazyLoadQuery` hook fetches and returns the data. It takes two arguments:

* The <span className="color1">GraphQL query</span> that we defined before.
* <span className="color2">Variables</span> that are passed to the server with the query. This query doesn’t declare any variables, so it’s an empty object.

The object that `useLazyLoadQuery` returns has the same shape as the query. For instance, if printed in JSON format it might look like this:

```
{
  topStory: {
    title: "Local Yak Named Yak of the Year",
    summary: "The annual Yak of the Year awards ceremony ...",
    poster: {
      name: "Baller Bovine Board",
      profilePicture: {
        url: '/images/baller_bovine_board.jpg',
      },
    },
    thumbnail: {
      url: '/images/max_the_yak.jpg',
    }
  }
}
```

Notice that each field selected by the GraphQL query corresponds to a property in the JSON response.

At this point, you should see a story fetched from the server:



:::note
The server's responses are artificially slowed down to make loading states perceptible, which will come in handy when we add more interactivity to the app. If you want to remove the delay, open `server/index.js` and remove the call to `sleep()`.
:::

The `useLazyLoadQuery` hook fetches the data when the component is first rendered. Relay also has APIs for pre-fetching the data before your app has even loaded — these are covered later. In any case, Relay uses Suspense to show a loading indicator until the data is available.

This is Relay in its most basic form: fetching the results of a GraphQL query when a component is rendered. As the tutorial progresses, we’ll see how Relay’s features fit together to make your app more maintainable — starting with a look at how Relay generates TypeScript types corresponding to each query.

<details>
<summary>Deep dive: Suspense for Data Loading</summary>

*Suspense* is a new API in React that lets React wait while data is loaded before it renders components that need that data. When a component needs to load data before rendering, React shows a loading indicator. You control the loading indicator's location and style using a special component called `Suspense`.

Right now, there's a `Suspense` component inside `App.tsx`, which is what shows the spinner while `useLazyLoadQuery` is loading data.

We'll look at Suspense in more detail in later sections when we add some more interactivity to the app.
</details>

<details>
<summary>Deep dive: Queries are Static</summary>

All of the GraphQL strings in a Relay app are pre-processed by the Relay compiler and removed from the resulting bundled code. This means you can’t construct GraphQL queries at runtime — they have to be static string literals so that they’re known at compile time. But it comes with major advantages.

First, it allows Relay to generate type definitions for the results of the query, making your code more type-safe.

Second, Relay replaces the GraphQL string literal with an object that tells Relay what to do. This is much faster than using the GraphQL strings directly at runtime.

Also, Relay’s compiler can be configured to [save queries to the server](/docs/guides/persisted-queries/) when you build your app, so that at runtime the client need only send a query ID instead of the query itself. This saves bundle size and network bandwidth, and can prevent attackers from writing malicious queries since only those your app was built with need be available.

So when you have a GraphQL tagged string literal in your program...

```
const MyQuery = graphql`
  query MyQuery {
    viewer {
      name
    }
  }
`;
```

... the JavaScript variable `MyQuery` is actually assigned to an object that looks something like this:

```
const MyQuery = {
  kind: "query",
  selections: [
    {
      name: "viewer",
      kind: "LinkedField",
      selections: [
        name: "name",
        kind: "ScalarField",
      ],
    }
  ]
};
```

along with various other properties and information. These data structures are carefully designed to allow the JIT to run Relay’s payload processing code very quickly. If you’re curious, you can use the [Relay Compiler Explorer](/compiler-explorer) to play with it.

</details>

* * *

## Relay and the Type System

You might notice that TypeScript reports an error with this code as we’ve written it:

```
const story = data.topStory;
                   ^^^^^^^^
Property 'topStory' does not exist on type 'unknown'
```

To fix this, we need to annotate the call to `useLazyLoadQuery` with types that Relay generates. That way, TypeScript will know what type `data` should have based on the fields we’ve selected in our query. Add the following:

```
// change-line
import type {NewsfeedQuery as NewsfeedQueryType} from './__generated__/NewsfeedQuery.graphql';

function Newsfeed({}) {
  const data = useLazyLoadQuery
  // change-line
  <NewsfeedQueryType>
  (NewsfeedQuery, {});
  ...
}
```

If we look inside `__generated__/NewsfeedQuery.graphql` we’ll see the following type definition — with the annotation we’ve just added, TypeScript knows that `data` should have this type:

```
export type NewsfeedQuery$data = {
  readonly topStory: {
    readonly poster: {
      readonly name: string | null;
      readonly profilePicture: {
        readonly url: string;
      } | null;
    };
    readonly summary: string | null;
    readonly thumbnail: {
      readonly url: string;
    } | null;
    readonly title: string;
  } | null;
};
```

 The Relay compiler generates TypeScript types corresponding to every piece of GraphQL that you have in your app within a <code>graphql``</code> literal. As long as <code>npm run dev</code> is running, the Relay compiler will automatically regenerate these files whenever you save one of your JavaScript source files, so you don’t need to refresh anything to keep them up to date.

Using Relay’s generated types makes your app safer and more maintainable. In addition to TypeScript, Relay supports the Flow type system if you want to use that instead. When using Flow, the extra annotation on `useLazyLoadQuery` is not needed, because Flow directly understands the contents of the <code>graphql``</code> tagged literal.

We’ll revisit types throughout this tutorial. But next, we'll look at an even more important way that Relay helps us with maintainability.

* * *

## Summary

Queries are the foundation of fetching GraphQL data. We’ve seen:

* How to define a GraphQL query within our app using the <code>graphql``</code> tagged literal.
* How to use the `useLazyLoadQuery` hook to fetch the results of a query when a component renders.
* How to import Relay's generated types for type safety.

In the next section, we’ll look at Fragments, one of the most core and distinctive aspects of Relay. Fragments let each individual component define its own data requirements, while retaining the performance advantages of issuing a single query to the server.

---

### Tutorial Queries 2 (`website/docs/tutorial/queries-2.mdx`)

# Queries for Interactions

We’ve seen how fragments let us specify data requirements in each component, yet at runtime perform only a single query for an entire screen. Here we’ll look at a situation where we *want* a second query on the same screen. This will also let us explore some more features of GraphQL queries.

* We’ll build a hovercard that shows more details about the poster of a story when you hover over their name.
* The hovercard will use a second query to fetch additional information that’s only needed if the user hovers.
* We’ll use **query variables** to tell the server which person we’d like more details about.
* We’ll see how to improve performance with **preloaded queries**.

After covering these topics, we’ll return to look at some more advanced features of Fragments.

* * *

In this section we’ll add a hovercard to `PosterByline` so that you can see more details about the poster of a story by hovering over their name.

<details>
<summary>Deep dive: When to use a secondary query</summary>

We've mentioned before that Relay is designed to help you fetch all of your data requirements for an entire screen up-front. But we can generalize this and say that it's a *user interaction* that should have at most one query. Navigating to another screen is just one common type of user interaction.

Within a screen, some interactions may disclose additional data from what was shown initially. If an interaction is performed relatively rarely, but needs a significant amount of additional data, it can be smart to fetch that additional data in a second query, performed when the interaction happens, rather than up-front when the screen is first loaded. This makes that initial load faster and less expensive.

There are also some interactions where the amount of data fetched is indefinite — e.g., a hovercard within a hovercard — and not feasible to know statically.

If data is lower-priority and should be loaded after the main data has loaded, but should pop in automatically without further user input, Relay has a feature called a *deferred fragment* for that. We'll cover it later.
</details>

We’ve already prepared a hovercard component that you can put to use. However, it has been in a directory called `future` in order to avoid compilation errors since it uses `ImageFragment`. Now that we’re at this stage of the tutorial, you can move the modules in `future` into `src/components`:

```shell
mv future/* src/components
```

Now, if you did the exercise to make `PosterByline` use fragments, the `PosterByline` component should look something like this:

```
export default function PosterByline({ poster }: Props): React.ReactElement {
  const data = useFragment(PosterBylineFragment, poster);
  return (
    <div className="byline">
      <Image image={data.profilePicture} width={60} height={60} className="byline__image" />
      <div className="byline__name">{data.name}</div>
    </div>
  );
}
```

To use the hovercard component, you can make the following changes:

```
// change-line
import Hovercard from './Hovercard';
// change-line
import PosterDetailsHovercardContents from './PosterDetailsHovercardContents';
// change-line
const {useRef} = React;

...

export default function PosterByline({ poster }: Props): React.ReactElement {
  const data = useFragment(PosterBylineFragment, poster);
  // change-line
  const hoverRef = useRef(null);
  return (
    <div
      // change-line
      ref={hoverRef}
      className="byline">
      <Image image={data.profilePicture} width={60} height={60} className="byline__image" />
      <div className="byline__name">{data.name}</div>
      // change
      <Hovercard targetRef={hoverRef}>
        <PosterDetailsHovercardContents />
      </Hovercard>
      // end-change
    </div>
  );
}
```

You should now see that whenever you hover over someone’s name, you get a hovercard with more information. If you look inside `PosterDetailsHovercardContents.tsx`, you’ll find that it performs a second query with `useLazyLoadQuery` to fetch additional information when that component is mounted.

There’s just one problem: it always shows the same person's information, no matter which poster you hover over!



* * *

## Query Variables

We need to tell the server *which* information we want more information about. GraphQL lets us define *query variables* that can be passed as arguments to specific fields. These arguments are then available on the server.

In the previous section, we saw how a field can accept arguments, but the argument values were hard-coded, e.g. `url(width: 200, height: 200)`. With query variables, we can determine these values at runtime. They’re passed from the client to the server alongside the query itself. GraphQL variables always begin with a `$` dollar sign.

Take a look inside `PosterDetailsHovercardContents.tsx`: you should see a query like this one:

```
const PosterDetailsHovercardContentsQuery = graphql`
  query PosterDetailsHovercardContentsQuery {
    // color1
    node(id: "1") {
      // color2
      ... on Actor @alias(as: "actor") {
        ...PosterDetailsHovercardContentsBodyFragment
      }
    }
  }
`;
```

<p><span className="color1">The <code>node</code> field</span> is a top-level field defined in our schema that lets us fetch any graph node given its unique ID. It takes the ID as an argument, which is currently hard-coded. In this exercise, we’ll be replacing this hard-coded ID with a variable supplied by our UI state.</p>

The funny-looking `... on Actor` is a <span className="color2">*type refinement*</span>. We’ll look at these in more detail in the next section and can ignore it for now. In brief, since we could supply any ID at all to the `node` field, there’s no way to know statically what *type* of node we’d be selecting. The type refinement specifies what type we expect, allowing us to use fields from the `Actor` type. Because the node might not actually be an `Actor` at runtime, we tag the refinement with [`@alias(as: "actor")`](../guides/alias-directive.mdx), which exposes it as a nullable `actor` field on `node` — that's why the component below reads `data.node?.actor`.

Within that, we simply spread a fragment that contains the fields we want to show — about which more later. For now, here are the steps to take to replace this hard-coded ID with the ID of the poster we’re hovering over:

### Step 1 — define a query variable

First we need to edit our query to declare that it accepts a query variable. Here’s the change:

```
const PosterDetailsHovercardContentsQuery = graphql`
  query PosterDetailsHovercardContentsQuery(
    // change-line
    $posterID: ID!
  ) {
    node(id: "1") {
      ... on Actor @alias(as: "actor") {
        ...PosterDetailsHovercardContentsBodyFragment
      }
    }
  }
`;
```

* The variable name is `$posterID`. This is the symbol we’ll use within the rest of the GraphQL query to refer to the value passed in from the UI.
* Variables have a type — in this case `ID!`*.* The `ID` type is a synonym for `String` that is used for node IDs to help distinguish them from other strings. The `!` on `ID!` means that field is non-nullable. In GraphQL, fields are normally nullable and non-nullability is the exception.

### Step 2 — pass the variable in as a field argument

Now we replace the hard-coded `"1"`  with our new variable:

```
const PosterDetailsHovercardContentsQuery = graphql`
  query PosterDetailsHovercardContentsQuery($posterID: ID!) {
    node(
      // change-line
      id: $posterID
    ) {
    ... on Actor @alias(as: "actor") {
      ...PosterDetailsHovercardContentsBodyFragment
      }
    }
  }
`;
```

:::note
You can use query variables not only as field arguments, but as arguments to fragments.
:::

### Step 3 — provide the argument value to useLazyLoadQuery

Now we need to pass in the actual value from our UI at runtime. The `useLazyLoadQuery` hook’s second argument is an object with variable values. We’ll add a new prop to our component and pass its value in there:

```
export default function PosterDetailsHovercardContents({
  // change-line
  posterID,
}: {
  // change-line
  posterID: string;
}): React.ReactElement {
  const data = useLazyLoadQuery<QueryType>(
    PosterDetailsHovercardContentsQuery,
    // change-line
    {posterID},
  );
  return <PosterDetailsHovercardContentsBody poster={data.node?.actor} />;
}
```

### Step 4 — pass the ID in from the parent component

Now we need to supply the `posterID` prop from the hovercard’s parent component, which is `PosterByline`. Head over to that file and add `id` to its fragment — then pass the ID in as a prop:

```
const PosterBylineFragment = graphql`
  fragment PosterBylineFragment on Actor {
    // change-line
    id
    ...
  }
`;

export default function PosterByline({ poster }: Props): React.ReactElement {
  ...
  return (
   ...
    <PosterDetailsHovercardContents
      // change-line
      posterID={data.id}
    />
   ...
  );
}
```

At this point, the hovercard should show the appropriate information for each poster that we hover over.



If you use the Network inspector in your browser, you should be able to find that the variable value is being passed alongside the query:



You may also notice that this request is made only the first time you hover over a particular poster. Relay caches the results of the query and re-uses them after that, until eventually removing the cached data if it hasn’t been used recently.

<details>
<summary>Deep dive: Caching and the Relay Store</summary>

In contrast to most other systems, Relay’s caching is not based on queries, but on graph nodes. Relay maintains a local cache of all the nodes it has fetched called the Relay Store. Each node in the Store is identified and retrieved by its ID. If two queries ask for the same information, as identified by node IDs, then the second query will be fulfilled using the cached information retrieved for the first query, and not be fetched.  Make sure to configure [missing field handlers](/docs/guided-tour/reusing-cached-data/filling-in-missing-data/) to take advantage of this caching behavior.

Relay will garbage-collect nodes from the Store if they aren’t “reachable” from any queries that are used, or have been recently used, by any mounted components.
</details>

<details>
<summary>Deep dive: Why GraphQL Needs a Syntax for Variables</summary>

You might be wondering why GraphQL even has the concept of variables, instead of just interpolating the value of the variables into the query string. Well, [as mentioned before](../queries-1), the text of the GraphQL query string isn’t available at runtime, because Relay replaces it with a data structure that is more efficient. You can also configure Relay to use *prepared queries*, where the compiler uploads each query to the server at build time and assigns it an ID — in that case, at runtime, Relay is just telling the server “Give me query #1337”, so string interpolation isn't possible and therefore the variables have to come out of band. Even when the query string is available, passing variable values separately eliminates any issues with serializing arbitrary values and escaping strings, above what is required with any HTTP request.
</details>

* * *

## Preloaded Queries

This example app is very simple, so performance isn't an issue. (In fact, the server is artificially slowed down in order to make loading states perceptible.) However, one of Relay's main concerns is to make performance as fast as possible in real apps.

Right now, the hovercard uses the `useLazyLoadQuery` hook, which fetches the query when the component is rendered. That means the timeline looks something like this:



Ideally, we should start the network fetch as early as possible, but here we don't start it until React is finished rendering. This timeline could look even worse if we used `React.lazy` to load the code for the hovercard component itself when the interaction happened. In that case, it would look like this:



Notice how we’re waiting around before we even start fetching the GraphQL query. It would be better if the query fetch began before the React component even rendered, right at the beginning in the mouse event handler itself. Then the timeline would look like this:



When the user interacts, we should immediately start fetching the query we need, while also beginning to render the component (fetching its code first if needed). Once both of these async processes are complete, we can render the component with the data available and show it to the user.

Relay provides a feature called *preloaded queries* that let us do this.

Let’s modify the hovercard to use preloaded queries.

### Step 1 — change useLazyLoadQuery to usePreloadedQuery

As a reminder, this is the `PosterDetailsHovercardContents` component that currently fetches the data lazily:

```
export default function PosterDetailsHovercardContents({
  posterID,
}: {
  posterID: string;
}): React.ReactElement {
  const data = useLazyLoadQuery<QueryType>(
    PosterDetailsHovercardContentsQuery,
    {posterID},
  );
  return <PosterDetailsHovercardContentsBody poster={data.node?.actor} />;
}
```

It calls `useLazyLoadQuery` which accepts *variables* as its second argument. We want to change this to `usePreloadedQuery`. However, with preloaded queries, the variables are actually determined when the query is fetched, which will be before this component is even rendered. So instead of variables, this hook takes a *query reference* that contains the information it needs to retrieve the results of the query. The query reference will be created when we fetch the query in Step 2.

Change the component as follows:

```
import {usePreloadedQuery} from 'react-relay';
import type {PreloadedQuery} from 'react-relay';
import type {PosterDetailsHovercardContentsQuery as QueryType} from './__generated__/PosterDetailsHovercardContentsQuery.graphql';

export default function PosterDetailsHovercardContents({
  // change-line
  queryRef,
}: {
  // change-line
  queryRef: PreloadedQuery<QueryType>,
}): React.ReactElement {
  // change-line
  const data = usePreloadedQuery(
    PosterDetailsHovercardContentsQuery,
    // change-line
    queryRef,
  );
  ...
}
```

:::note
We’ll be modifying the parent component, `PosterByline`, to have it initiate the `PosterDetailsHovercardContentsQuery` query. Since it needs a reference to the query, the query needs to be exported:
```
export const PosterDetailsHovercardContentsQuery = graphql`...
```
:::


### Step 2 — Call useQueryLoader in the parent component

Now that `PosterDetailsHovercardContents` expects a query ref, we need to create that query ref and pass it down from the parent component, which is `PosterByline`. We create the query ref using a hook called `useQueryLoader`. This hook also returns a function that we call in our event handler to trigger the query fetch.

```
import {useQueryLoader} from 'react-relay';
import type {PosterDetailsHovercardContentsQuery as HovercardQueryType} from './__generated__/PosterDetailsHovercardContentsQuery.graphql';
import {PosterDetailsHovercardContentsQuery} from './PosterDetailsHovercardContents';

export default function PosterByline({ poster }: Props): React.ReactElement {
  ...
  // change
  const [
    hovercardQueryRef,
    loadHovercardQuery,
  ] = useQueryLoader<HovercardQueryType>(PosterDetailsHovercardContentsQuery);
  // end-change
  return (
   ...
    <PosterDetailsHovercardContents
      // change-line
      queryRef={hovercardQueryRef}
    />
   ...
  );
}
```

The `useQueryLoader` hook returns two things we need:

* The query ref is an opaque piece of information that `usePreloadedQuery` will use to retrieve the result of the query.
* `loadHovercardQuery` is a function that will initiate the request.

### Step 3 — Fetch the query in the event handler

Finally, we need to call `loadHovercardQuery` in an event handler that happens when the card is shown. Luckily the `Hovercard` component has a `onBeginHover` event that we can use:

```
export default function PosterByline({ poster }: Props): React.ReactElement {
  ...
  const [
    hovercardQueryRef,
    loadHovercardQuery,
  ] = useQueryLoader<HovercardQueryType>(PosterDetailsHovercardContentsQuery);
  // change
  function onBeginHover() {
    loadHovercardQuery({posterID: data.id});
  }
  // end-change
  return (
    <div className="byline">
      ...
      <Hovercard
        // change-line
        onBeginHover={onBeginHover}
        targetRef={hoverRef}>
        <PosterDetailsHovercardContents queryRef={hovercardQueryRef} />
      </Hovercard>
    </div>
  );
}
```

Note that the query variables are now passed in here where we initiate the request.

At this point, you should see the same behavior as before, but now it will be a little bit faster since Relay can get the query started earlier.

:::tip
Although we introduced queries using `useLazyLoadQuery` for simplicity, preloaded queries are always the preferred way to use queries in Relay because they can significantly improve performance in the real world. With the appropriate [integrations with your server and router system](https://github.com/relayjs/relay-examples/tree/main/issue-tracker-next-v13), you can even preload the main query for a webpage on the server side before you’ve even downloaded or run any client code.
:::

* * *

## Summary

* Although all of the data initially shown on a screen should be combined into one query, user interactions needing further information can be handled with secondary queries.
* Query variables let you pass information to the server along with your query.
* Query variables are used by passing them into field arguments.
* Preloaded queries are always the best way to go. For user interaction queries, initiate the fetch in the event handler. For the initial query for your screen, initiate the fetch as early as possible in your specific routing system. Use lazy-loaded queries only for quick prototyping, or not at all.

Next we'll briefly look at a way to enhance the hovercard by handling different types of posters differently. After that, we'll see how to handle situations where information that's part of the initial query also needs to be updated and refetched with different variables.

---

### Tutorial Refetchable Fragments (`website/docs/tutorial/refetchable-fragments.mdx`)

# Refetchable Fragments

In this section, we'll look at how to fetch different data in response to user input.

* We'll build a **filterable friends list**.
* We'll see how to refetch only the necessary data, not an entire query.

* * *

Since Relay encourages you to fetch all of your data in one big query, what happens when you need to refetch some data with different variables?

For example, suppose you were building a filterable list. You would need to fetch new search results when the search input changed.

One way to approach this would be to use a separate, secondary query to fetch the list, much like we did to fetch the hovercard earlier. Then we could change the query variables and refetch the query when the input changed.

However, this isn't optimal, because it needlessly uses a second query to fetch the *initial* list, before any user input occurs. The hovercard only appeared in response to a user interaction, but if the filterable list is visible and ready to be filtered, we might as well get its initial contents as part of our big query.

On the other hand, we don't want to refetch the *entire big query* whenever the input changes. Not only would this mean retrieving a large amount of data unnecessarily, it could disrupt other parts of the UI. If certain data unrelated to the filterable list has changed on the server, it would appear to randomly change when the query was refetched. Besides, this would mean threading the user input up to the top of the React tree where the query lives, which would not scale very well.

To address these issues, Relay provides *refetchable fragments*. These are fragments that can be refetched with new variables, separately from the rest of the query that they get spread into. They allow us to change a fragment’s arguments and fetch new data for the new argument values, just as we can fetch an entire query with new query variables.

But fragments are just that, fragments — they aren’t queries and can’t be fetched without being spread into a query and read out from the query results. So how do refetchable fragments actually work? The answer is that the Relay compiler generates a new, separate query just to refetch the fragment. The data is retrieved *initially* as part of whatever larger query the fragment is spread into, but then when it’s refetched, the new synthetic query is used.

* * *

To try this out, let's add a sidebar to the page with a filterable contacts list. After all, it wouldn't feel like a properly cozy newsfeed app without the ability to contact people.

We've already prepared a `Sidebar` component, you just need to drop it into `App.tsx`:

```
// change-line
import Sidebar from './Sidebar';

export default function App(): React.ReactElement {
  return (
    <RelayEnvironment>
      <React.Suspense fallback={<LoadingSpinner />}>
        <div className="app">
          <Newsfeed />
          // change-line
          <Sidebar />
        </div>
      </React.Suspense>
    </RelayEnvironment>
  );
}
```

You should now see a sidebar with a list of people at the top.



Have a look at `ContactsList.tsx` and you’ll find this fragment, which is what selects the list of contacts:

```
const ContactsListFragment = graphql`
  fragment ContactsListFragment on Viewer {
    contacts {
      id
      ...ContactRowFragment
    }
  }
`;
```

As it happens, the `contacts` field accepts a `search` argument that filters the list. You can try it out by changing `contacts` in this fragment to `contacts(search: "S")`. If you run `npm run relay` and refresh the page, you should see only those contacts that have the letter S in them.

Our goal, then, will be to hook up a search input so that, when the input changes, we refetch *just this fragment* with a new value for that `search` argument.

:::tip
As an optional exercise, try combining the queries of Sidebar and Newsfeed into a single query. There is no need for Sidebar to have its own query separate from Newsfeed; in a real app they would both have fragments and the *entire screen* would have only a single query. We built it with a separate query to simplify the early examples in the tutorial.
:::

### Step 1 — Add a fragment argument

First we need to make this fragment accept an argument. With refetchable fragments, fragment arguments become query variables for the refetch query that Relay generates. (They also work like regular fragment arguments, so the parent query can pass in an initial value for the argument.)

```
const ContactsListFragment = graphql`
  fragment ContactsListFragment on Viewer
    // change
    @argumentDefinitions(
      search: {type: "String", defaultValue: null}
    )
    // end-change
  {
    contacts {
      id
      ...ContactRowFragment
    }
  }
`;
```

### Step 2 — Pass the fragment argument as a field argument

Pass the fragment argument in as an argument to the `contacts` field.

```
const ContactsListFragment = graphql`
  fragment ContactsListFragment on Viewer
    @argumentDefinitions(
      search: {type: "String", defaultValue: null}
    )
  {
    // change-line
    contacts(search: $search) {
      id
      ...ContactRowFragment
    }
  }
`;
```

Remember, the first `search` here is the name of the argument to `contacts`, while the second `$search` is the variable created by our fragment argument.

### Step 3 — Add the @refetchable directive

Next we'll add a `@refetchable` directive. This tells Relay to generate the extra query for refetching it. You have to specify the name of the generated query — it's a good idea to base it on the name of the fragment.

```
const ContactsListFragment = graphql`
  fragment ContactsListFragment on Viewer
    // change-line
    @refetchable(queryName: "ContactsListRefetchQuery")
    @argumentDefinitions(
      search: {type: "String", defaultValue: null}
    )
  {
     // ...
  }
`;
```

### Step 4 — Add the search input

Now we need to actually hook this up to our UI. Take a look at the `ContactsList` component:

```
export default function ContactsList({ viewer }: Props) {
  const data = useFragment(ContactsListFragment, viewer);
  return (
    <Card dim={true}>
      <h3>Contacts</h3>
      {data.contacts.map(contact =>
        <ContactRow key={contact.id} contact={contact} />
      )}
    </Card>
  );
}
```

First we need to add a search field.

```
// change-line
import SearchInput from './SearchInput';

// change-line
const {useState} = React;

function ContactsList({viewer}) {
  const data = useFragment(ContactsListFragment, viewer);
  // change-line
  const [searchString, setSearchString] = useState('');
  // change
  const onSearchStringChanged = (value: string) => {
    setSearchString(value);
  };
  // end-change
  return (
    <Card dim={true}>
      <h3>Contacts</h3>
      // change
      <SearchInput
        value={searchString}
        onChange={onSearchStringChanged}
      />
      // end-change
      {data.contacts.map(contact =>
        <ContactRow key={contact.id} contact={contact} />
      )}
    </Card>
  );
}
```

### Step 5 — Call useRefetchableFragment

Now to refetch the fragment when the string changes, we change `useFragment` to `useRefetchableFragment`. This hook returns a `refetch` function which will refetch the fragment with new variables which we provide as an argument.

```
// change-line
import {useRefetchableFragment} from 'react-relay';

function ContactsList({viewer}) {
  // change-line
  const [data, refetch] = useRefetchableFragment(ContactsListFragment, viewer);
  const [searchString, setSearchString] = useState('');
  const onSearchStringChanged = (value) => {
    setSearchString(value);
    // change-line
    refetch({search: value});
  };
  return (
    // ...
  );
}
```

You’ll notice that Relay gives us a callback for refetching, rather than accepting the new state variables as an argument to the hook and refetching when it is re-rendered  with a different value. This means that the fetch begins as soon as the event takes place, saving some time versus waiting until React finishes re-rendering — the same principle we saw before with preloaded queries. It also gives us more control, for example if we wanted to debounce the refetch.

### Step 6 — Control loading with useTransition

At this point, when the fragment is refreshed, Relay uses Suspense while the new data is loading, so the entire component is replaced with a spinner! This makes the UI fairly unusable. We would rather just keep the current data on screen until the new data is available.

The way Suspense normally works is this: When a component is missing data that it needs to render (as our component does after we refetch), it tells React to wait. When this happens, React finds the nearest Suspense component in the tree. It then replaces everything under that component with a "fallback" loading indicator.





This makes sense when initially loading a screen, but in this instance there's no reason to hide the existing UI and replace it with a spinner. While React is waiting, it can simply continue showing what's already there.

To achieve this, we can mark the refetch as a *transition*. Transitions are React state updates that do not need to be immediately responded to — React can wait until the data is available.

Transitions are marked by wrapping the state change in a call to a function provided by the `useTransition` hook. This is what the code will look like:

```
// change-line
const {useState, useTransition} = React;

function ContactsList({viewer}) {
  // change-line
  const [isPending, startTransition] = useTransition();
  const [searchString, setSearchString] = useState('');
  const [data, refetch] = useRefetchableFragment(ContactsListFragment, viewer);
  const onSearchStringChanged = (value) => {
    setSearchString(value);
    // change
    startTransition(() => {
      refetch({search: value});
    });
    // end-change
  };
  return (
    <Card dim={true}>
      <h3>Contacts</h3>
      <SearchInput
        value={searchString}
        onChange={onSearchStringChanged}
        // change-line
        isPending={isPending}
      />
      {data.contacts.map(contact =>
        <ContactRow key={contact.id} contact={contact} />
      )}
    </Card>
  );
}
```

While React is waiting for the new data, instead of using a Suspense fallback, React re-renders the component with the `isPending` flag set to true.

We simply pass the `isPending` flag to `SearchInput` (which causes it to show a spinner) while the refetch is happening. Meanwhile, by placing `setSearchString` outside of the transition but `refetch` within it, we tell React to immediately update the search input.

We should now be able to search the contacts list with a nice user experience, showing a spinner but keeping the previous data visible while loading.



<details>
<summary>Deep dive: What fragments can be refetched?</summary>

To refetch fragments, Relay has to know how to generate a query that lets it refetch just the information from the fragment. That’s only possible for fragments that meet certain requirements.

You might imagine that we could, if nothing else, re-run the original query that the fragment was spread into. However, GraphQL doesn’t guarantee that the same query will return the same results at different times. For instance, imagine you had a GraphQL field that returned the top trending posts across the site:

```
query MyQuery {
  topTrendingPosts {
    title
    summary
    date
    poster {
     ...PosterFragment
    }
  }
}
```

If you wanted to refresh just `PosterFragment` from this query, it wouldn’t work to construct a query like this:

```
query MyQuery {
  topTrendingPosts {
    poster {
     ...PosterFragment
    }
  }
}
```

... because the top trending post could be a different post by the time you refresh it!

Relay needs a way of identifying the specific node in the graph that the fragment ends up on, even if it can no longer be reached by the same path that the original query uses. If the node has a unique and stable ID, then we can just have a convention for querying for “the graph node with some specific ID” like so:

```
query RefetchQuery {
  node(id: "abcdef") {
    ...PosterFragment
  }
}
```

In fact, this is exactly the convention that Relay uses. It expects your server to implement a top-level field called `node` that takes an ID and gives you the graph node with that ID. (We saw `node` earlier with the hovercard example — there it was used to fetch a specific person given their ID using a secondary query.)

Not every graph node has a stable ID — some are ephemeral. To be used with `node`, your schema has to declare that its type implements an interface called `Node`:

```
type Person implements Node {
  id: ID!
  ...
}
```

The `Node` interface simply says it has an ID, but more importantly indicates by convention that that ID is stable and unique:

```
interface Node {
  id: ID!
}
```

import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

Besides fragments on types that implement `Node`, you can also refetch fragments that are on `Viewer` (since the viewer is assumed to be stable throughout a session) and that are at the top level of a query (since there’s no field above them that could change identity).

<FbInternalOnly>

Meta only: Ents marked with <a href="https://fb.workplace.com/groups/graphql.fyi/permalink/1539541276187011/" target="_blank">GraphQLFetchable</a> can also be refetched.

</FbInternalOnly>

</details>

* * *

## Summary

Refetchable fragments let us efficiently update specific parts of the UI in response to user input, while initializing them as part of the same query that we use for the entire screen.

Relay's pagination features are built on refetchable fragments, too. We'll explore those next.

---

### Api Reference Entrypoint Apis Entrypoint Container (`website/docs/api-reference/entrypoint-apis/entrypoint-container.mdx`)

---
id: entrypoint-container
title: EntryPointContainer
slug: /api-reference/entrypoint-container/
description: API reference for EntryPointContainer, a React component used to render the root component of an entrypoint
keywords:
  - entrypoint
  - container
  - root
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## `EntryPointContainer`

<FbInternalOnly>

For more information, see the [Defining EntryPoints](../../guides/entrypoints/using-entrypoints/#defining-entrypoints) and [Consuming EntryPoints](../../guides/entrypoints/using-entrypoints/#-entrypoints) guides.

</FbInternalOnly>

```js
function EntryPointContainer({
  entryPointReference,
  props,
}: {
  +entryPointReference: PreloadedEntryPoint<TEntryPointComponent>,
  +props: TRuntimeProps,
}): ReactElement
```

A React component that renders a preloaded EntryPoint.

* `entryPointReference`: the value returned from a call to `loadEntryPoint` or acquired from the `useEntryPointLoader` hook.
* `props`: additional runtime props that will be passed to the `Component`

<DocsRating />

---

### Api Reference Entrypoint Apis Load Entrypoint (`website/docs/api-reference/entrypoint-apis/load-entrypoint.mdx`)

---
id: load-entrypoint
title: loadEntryPoint
slug: /api-reference/load-entrypoint/
description: API reference for loadEntryPoint, which imperatively loads an entrypoint and data for its queries
keywords:
  - entrypoint
  - preload
  - render-as-you-fetch
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## `loadEntryPoint`

This function is designed to be used with `EntryPointContainer` to implement the "render-as-you-fetch" pattern.

EntryPoint references returned from `loadEntryPoint` will leak data to the Relay store (if they have associated queries) unless `.dispose()` is called on them once they are no longer referenced. As such, prefer using `useEntryPointLoader` when possible, which ensures that EntryPoint references are correctly disposed for you. See the [`useEntryPointLoader`](../use-entrypoint-loader) docs for a more complete example.

<FbInternalOnly>

For more information, see the [Loading EntryPoints](../../guides/entrypoints/using-entrypoints/#loading-entrypoints) guide.

</FbInternalOnly>

```js
const EntryPoint = require('MyComponent.entrypoint.js');

const {loadQuery} = require('react-relay');

// Generally, your component should access the environment from the React context,
// and pass that environment to this function.
const getEntrypointReference = environment => loadEntryPoint(
  { getEnvironment: () => environment },
  EntryPoint,
  {id: '4'},
);

// later: pass entryPointReference to EntryPointContainer
// Note that EntryPoint references should have .dispose() called on them,
// which is missing in this example.
```

### Arguments

* `environmentProvider`: A provider for a Relay Environment instance on which to execute the request. If you're starting this request somewhere within a React component, you probably want to use the environment you obtain from using [`useRelayEnvironment`](../use-relay-environment/).
* `EntryPoint`: EntryPoint to load.
* `entryPointParams`: Parameters that will be passed to the EntryPoint's `getPreloadProps` method.

### Flow Type Parameters

* `TEntryPointParams`: Type parameter corresponding to the type of the first parameter of the `getPreloadProps` method of the EntryPoint.
* `TPreloadedQueries`: the type of the `queries` parameter to the EntryPoint component.
* `TPreloadedEntryPoints`: the type of the `entrypoints` parameter passed to the EntryPoint component.
* `TRuntimeProps`: the type of the `props` prop passed to `EntryPointContainer`. This object is passed down to the EntryPoint component, also as `props`.
* `TExtraProps`: if an EntryPoint's `getPreloadProps` method returns an object with an `extraProps` property, those extra props will be passed to the EntryPoint component as `extraProps`.
* `TEntryPointComponent`: the type of the EntryPoint.
* `TEntryPoint`: the type of the EntryPoint.

### Return Value

An EntryPoint reference with the following properties:

* `dispose`: a method that will release any query references loaded by this EntryPoint (including indirectly, by way of other EntryPoints) from being retained by the store. This can cause the data referenced by these query reference to be garbage collected.

The exact format of the return value is *unstable and highly likely to change*. We strongly recommend not using any other properties of the return value, as such code would be highly likely to break when upgrading to future versions of Relay. Instead, pass the result of `loadEntryPoint()` to `EntryPointContainer`.

### Behavior

* When `loadEntryPoint()` is called, each of an EntryPoint's associated queries (if it has any) will load their query data and query AST. Once both the query AST and the data are available, the data will be written to the store. This differs from the behavior of `prepareEntryPoint_DEPRECATED`, which would only write the data from an associated query to the store when that query was rendered with `usePreloadedQuery`.
* The EntryPoint reference's associated query references will be retained by the Relay store, preventing the data from being garbage collected. Once you call `.dispose()` on the EntryPoint reference, the data from the associated queries is liable to be garbage collected.
* `loadEntryPoint` may throw an error if it is called during React's render phase.



<DocsRating />

---

### Api Reference Entrypoint Apis Use Entrypoint Loader (`website/docs/api-reference/entrypoint-apis/use-entrypoint-loader.mdx`)

---
id: use-entrypoint-loader
title: useEntryPointLoader
slug: /api-reference/use-entrypoint-loader/
description: API reference for useEntryPointLoader, a React hook used to load entrypoints in response to user events
keywords:
  - render-as-you-fetch
  - entrypoint
  - preload
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## `useEntryPointLoader`

Hook used to make it easy to safely work with EntryPoints, while avoiding data leaking into the Relay store. It will keep an EntryPoint reference in state, and dispose of it when it is no longer accessible via state.

<FbInternalOnly>

For more information, see the [Loading EntryPoints](https://www.internalfb.com/intern/wiki/Relay/Guides/entry-points/#loading-entrypoints) guide.

</FbInternalOnly>

```js
const {useEntryPointLoader, EntryPointContainer} = require('react-relay');

const ComponentEntryPoint = require('Component.entrypoint');

function EntryPointRevealer(): React.MixedElement {
  const environmentProvider = useMyEnvironmentProvider();
  const [
    entryPointReference,
    loadEntryPoint,
    disposeEntryPoint,
  ] = useEntryPointLoader(environmentProvider, ComponentEntryPoint);

  return (
    <>
      {
        entryPointReference == null && (
          <Button onClick={() => loadEntryPoint({})}>
            Click to reveal the contents of the EntryPoint
          </Button>
        )
      }
      {
        entryPointReference != null && (
          <>
            <Button onClick={disposeEntryPoint}>
              Click to hide and dispose the EntryPoint.
            </Button>
            <Suspense fallback="Loading...">
              <EntryPointContainer
                entryPointReference={entryPointReference}
                props={{}}
              />
            </Suspense>
          </>
        )
      }
    </>
  );
}
```

### Arguments

* `environmentProvider`: an object with a `getEnvironment` method that returns a Relay environment.
* `EntryPoint`: the EntryPoint, usually acquired by importing a `.entrypoint.js` file.

### Flow Type Parameters

* `TEntryPointParams`: the type of the first argument to the `getPreloadProps` method of the EntryPoint.
* `TPreloadedQueries`: the type of the `queries` prop passed to the EntryPoint component.
* `TPreloadedEntryPoints`: the type of the `entryPoints` prop passed to the EntryPoint component.
* `TRuntimeProps`: the type of the `props` prop passed to `EntryPointContainer`. This object is passed down to the EntryPoint component, also as `props`.
* `TExtraProps`: if an EntryPoint's `getPreloadProps` method returns an object with an `extraProps` property, those extra props will be passed to the EntryPoint component as `extraProps` and have type `TExtraProps`.
* `TEntryPointComponent`: the type of the EntryPoint component.
* `TEntryPoint`: the type of the EntryPoint.

### Return value

A tuple containing the following values:

* `entryPointReference`: the EntryPoint reference, or `null`.
* `loadEntryPoint`: a callback that, when executed, will load an EntryPoint, which will be accessible as `entryPointReference`. If a previous EntryPoint was loaded, it will dispose of it. It may throw an error if called during React's render phase.
    * Parameters
        * `params: TEntryPointParams`: the params passed to the EntryPoint's `getPreloadProps` method.
* `disposeEntryPoint`: a callback that, when executed, will set `entryPointReference` to `null` and call `.dispose()` on it. It has type `() => void`. It should not be called during React's render phase.

### Behavior

* When the `loadEntryPoint` callback is called, each of an EntryPoint's associated queries (if it has any) will load their query data and query AST. Once both the query AST and the data are available, the data will be written to the store. This differs from the behavior of `prepareEntryPoint_DEPRECATED`, which would only write the data from an associated query to the store when that query was rendered with `usePreloadedQuery`.
* The EntryPoint reference's associated query references will be retained by the Relay store, preventing the data from being garbage collected. Once you call `.dispose()` on the EntryPoint reference, the data from the associated queries is liable to be garbage collected.
* The `loadEntryPoint` callback may throw an error if it is called during React's render phase.


<DocsRating />

---

### Api Reference Graphql Graphql Directives (`website/docs/api-reference/graphql/graphql-directives.mdx`)

---
id: graphql-directives
title: GraphQL Directives
slug: /api-reference/graphql-and-directives/
description: API Reference for GraphQL directives
keywords:
  - GraphQL
  - Directive
  - arguments
  - argumentDefinitions
  - connection
  - relay
  - inline
  - provider
---

import DocsRating from '@site/src/core/DocsRating'; import {FbInternalOnly,
OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

Relay uses directives to add additional information to GraphQL documents, which
are used by the [Relay compiler](../../guides/compiler/) to generate the
appropriate runtime artifacts. These directives only appear in your application
code and are removed from requests sent to your GraphQL server.

<OssOnly>

**Note:** The Relay compiler will maintain any directives supported by your server (such as `@include` or `@skip`) so they remain part of the request to the GraphQL server and won't alter generated runtime artifacts.

</OssOnly>
<FbInternalOnly>

**Note:** The Relay compiler will maintain any directives supported by your server (such as `@include` or `@skip`) so they remain part of the request to the GraphQL server and won't alter generated runtime artifacts. Additional directives are documented [here](https://www.internalfb.com/intern/wiki/GraphQL/APIs_and_References/Directives/#graphql-standard).

</FbInternalOnly>

## `@arguments`

`@arguments` is a directive used to pass arguments to a fragment that was
defined using [`@argumentDefinitions`](#argumentdefinitions). For example:

```graphql
query TodoListQuery($userID: ID) {
  ...TodoList_list @arguments(count: $count, userID: $userID) # Pass arguments here
}
```

## `@argumentDefinitions`

`@argumentDefinitions` is a directive used to specify arguments taken by a
fragment. For example:

```graphql
fragment TodoList_list on TodoList
@argumentDefinitions(
  count: {type: "Int", defaultValue: 10} # Optional argument
  userID: {type: "ID"} # Required argument
) {
  title
  todoItems(userID: $userID, first: $count) {
    # Use fragment arguments here as variables
    ...TodoItem_item
  }
}
```

### Provided Variables

A provided variable is a special fragment variable whose value is supplied by a
specified provider function at runtime. This simplifies supplying device
attributes, user experiment flags, and other runtime constants to graphql
fragments.

To add a provided variable:

- add an argument with `provider: "[JSModule].relayprovider"` to
  `@argumentDefinitions`
- ensure that `[JSModule].relayprovider.js` exists and exports a `get()`
  function
  - `get` should return the same value on every call for a given run.

```graphql
fragment TodoItem_item on TodoList
@argumentDefinitions(
  include_timestamp: {
    type: "Boolean!"
    provider: "Todo_ShouldIncludeTimestamp.relayprovider"
  }
) {
  timestamp @include(if: $include_timestamp)
  text
}
```

```javascript
// Todo_ShouldIncludeTimestamp.relayprovider.js
export default {
  get(): boolean {
    // must always return true or false for a given run
    return check('todo_should_include_timestamp');
  },
};
```

Notes:

<FbInternalOnly>

- Even though fragments declare provided variables in `argumentDefinitions`,
  their parent cannot pass provided variables through `@arguments`.
- An argument definition cannot specify both a provider and a defaultValue.
- If the modified fragment is included in operations that use hack preloaders
  (`@preloadable(hackPreloader: true)`), you will need to manually add provided
  variables when calling `RelayPreloader::gen`.
  - Hack's typechecker will fail with
    `The field __relay_internal__pv__[JsModule] is missing.`
  - We strongly encourage switching to
    [Entrypoints](../../guides/entrypoints/using-entrypoints/) if possible.
- _Unstable / subject to change_
  - Relay transforms provided variables to operation root variables and renames
    them to `__relay_internal__pv__[JsModule]`.
    - Only relevant if you are debugging a query that uses provided variables.

</FbInternalOnly>

<OssOnly>

- Even though fragments declare provided variables in `argumentDefinitions`,
  their parent cannot pass provided variables through `@arguments`.
- An argument definition cannot specify both a provider and a defaultValue.
- _Unstable / subject to change_
  - Relay transforms provided variables to operation root variables and renames
    them to `__relay_internal__pv__[JsModule]`.
    - Only relevant if you are debugging a query that uses provided variables.

</OssOnly>

## `@catch`

`@catch` is a directive you can add to fields, fragments, queries, mutations,
and aliased inline fragments in your Relay queries to declare how field-level
errors are handled in runtime.

See also [the @catch guide](../../guides/catch-directive/).

## `@connection(key: String!, filters: [String])`

With `usePaginationFragment`, Relay expects connection fields to be annotated
with a `@connection` directive. For more detailed information and an example,
check out the
[docs on `usePaginationFragment`](../../guided-tour/list-data/rendering-connections).

## `@refetchable(queryName: String!, directives: [String], preferFetchable: Boolean)`

With `useRefetchableFragment` and `usePaginationFragment`, Relay expects a
`@refetchable` directive. The `@refetchable` directive can only be added to
fragments that are "refetchable", that is, on fragments that are declared on
`Viewer` or `Query` types, or on a type that implements `Node` (i.e. a type that
has an id). The `@refetchable` directive will autogenerate a query with the
specified `queryName`. This will also generate Flow types for the query,
available to import from the generated file: `<queryName>.graphql.js`. For more
detailed information and examples, check out the docs on
[`useRefetchableFragment`](../use-refetchable-fragment/) or
[`usePaginationFragment`](../use-pagination-fragment/).

Optionally, you can pass in a list of directives to add to the autogenerated
query. For example, this can be used to add the `@relay_test_operation`
directive for [testing](../../guides/testing-relay-components):

[Optional] `preferFetchable: Boolean`

This argument tells the Relay compiler to prefer generating
`fetch_MyType(): MyType` queries for types that implement the `Node` interface.
This is useful for schemas that have adopted the `@strong` and `@fetchable`
server annotations for types. You can directly fetch concrete objects without
needing to refine `Node` interface to a specific type.

```javascript
graphql`
  fragment FriendsListComponent_user on User
  @refetchable(
    queryName: "FriendsListFetchQuery"
    directives: ["@relay_test_operation"]
  ) {
    ...
  }
`;
```

## `@relay(plural: Boolean)`

When defining a fragment for use with `useFragment`, you can use the
`@relay(plural: true)` directive to indicate that the hook expects the prop for
that fragment to be a list of items instead of a single item. A query or parent
that spreads a `@relay(plural: true)` fragment should do so within a plural
field (ie a field backed by a
[GraphQL list](http://graphql.org/learn/schema/#lists-and-non-null). For
example:

```javascript
// Plural fragment definition
graphql`
  fragment TodoItems_items on TodoItem @relay(plural: true) {
    id
    text
  }
`;

// Plural fragment usage: note the parent type is a list of items (`TodoItem[]`)
fragment TodoApp_app on App {
  items {
    // parent type is a list here
    ...TodoItem_items
  }
}
```

## `@required`

`@required` is a directive you can add to fields in your Relay queries to
declare how null values should be handled at runtime.

See also [the @required guide](../../guides/required-directive/).

## `@throwOnFieldError`

`@throwOnFieldError` is a directive you can add to your Relay queries and fragments to have Relay throw if any field errors are encountered when reading the query or fragment. Adding the directive will allow Relay to generate non-null types for any fields marked as `@semanticNonNull` in the schema.

See also [the @throwOnFieldError guide](../../guides/throw-on-field-error-directive/).

**Read more about Relay's experimental support for
[Semantic Nullability](../../guides/semantic-nullability.mdx).**

## `@semanticNonNull`

The `@semanticNonNull` directive can be added to fields in your schema to
indicate that the field is non-nullable in the semantic sense, but that the
client should still be prepared to handle errors.

**Read more about Relay's experimental support for
[Semantic Nullability](../../guides/semantic-nullability.mdx).**

## `@alias`

`@alias` is a directive that allows you to give a fragment spread or inline
fragment an alias, similar to a field alias. This is useful when you want to
conditionally include a fragment and check if it was fetched, or otherwise group
data together.

For fragment spreads, the alias will default to the fragment name. For inline
fragments, the alias will default to the type name. If you wish to supply your
own name, or you have an inline fragment without any type condition, you can
specify the alias using the `as` argument.

```graphql
fragment MyFragment on User {
  ... on User @alias(as: "myGreatAlias") {
    name
  }
}
```

See also [the @alias guide](../../guides/alias-directive/).

## `@inline`

The hooks APIs that Relay exposes allow you to read data from the store only
during the render phase. In order to read data from outside of the render phase
(or from outside of React), Relay exposes the `@inline` directive. The data from
a fragment annotated with `@inline` can be read using `readInlineData`.

In the example below, the function `processItemData` is called from a React
component. It requires an item object with a specific set of fields. All React
components that use this function should spread the `processItemData_item`
fragment to ensure all of the correct item data is loaded for this function.

```javascript
import {graphql, readInlineData} from 'react-relay';

// non-React function called from React
function processItemData(itemRef) {
  const item = readInlineData(
    graphql`
      fragment processItemData_item on Item @inline {
        title
        price
        creator {
          name
        }
      }
    `,
    itemRef,
  );
  sendToThirdPartyApi({
    title: item.title,
    price: item.price,
    creatorName: item.creator.name,
  });
}
```

```javascript
export default function MyComponent({item}) {
  function handleClick() {
    processItemData(item);
  }

  const data = useFragment(
    graphql`
      fragment MyComponent_item on Item {
        ...processItemData_item
        title
      }
    `,
    item,
  );

  return <button onClick={handleClick}>Process {item.title}</button>;
}
```

## `@relay(mask: Boolean)`

It is not recommended to use `@relay(mask: false)`. Please instead consider
using the `@inline` fragment.

`@relay(mask: false)` can be used to prevent data masking; when including a
fragment and annotating it with `@relay(mask: false)`, its data will be
available directly to the parent instead of being masked for a different
container.

Applied to a fragment definition, `@relay(mask: false)` changes the generated
Flow types to be better usable when the fragment is included with the same
directive. The Flow types will no longer be exact objects and no longer contain
internal marker fields.

This may be helpful to reduce redundant fragments when dealing with nested or
recursive data within a single Component.

Keep in mind that it is typically considered an **anti-pattern** to create a
single fragment shared across many containers. Abusing this directive could
result in over-fetching in your application.

In the example below, the `user` prop will include the data for `id` and `name`
fields wherever `...Component_internUser` is included, instead of Relay's normal
behavior to mask those fields:

```javascript
graphql`
  fragment Component_internUser on InternUser @relay(mask: false) {
    id
    name
  }
`;
```

## `@waterfall`

With [Relay Resolvers](../../guides/relay-resolvers/introduction.mdx) it's
possible to create client-defined edges in the graph which point to server
types. When reading these edge fields, Relay is forced to lazily fetch the
server data for the edge. This will force Relay to make a second request to the
server to fetch the data for the edge.

To highlight this tradeoff both in the editor and during code review, the Relay
compiler expects all reads of these fields to be annotated as `@waterfall`.

```graphql
fragment EditPost on DraftPost {
  author @waterfall {
    name
  }
}
```

See the [Return Type](../../guides/relay-resolvers/return-types.mdx#server-types)
portion of the Relay Resolvers guide for more information.

<DocsRating />

---

### Api Reference Hooks  Use Lazy Load Query Extra (`website/docs/api-reference/hooks/_use-lazy-load-query-extra.mdx`)

### Behavior

* It is expected for `useLazyLoadQuery` to have been rendered under a [`RelayEnvironmentProvider`](../relay-environment-provider), in order to access the correct Relay environment, otherwise an error will be thrown.
* Calling `useLazyLoadQuery`  will fetch and render the data for this query, and it may [*_suspend_*](../../guided-tour/rendering/loading-states) while the network request is in flight, depending on the specified `fetchPolicy`, and whether cached data is available, or if it needs to send and wait for a network request. If `useLazyLoadQuery` causes the component to suspend, you'll need to make sure that there's a `Suspense` ancestor wrapping this component in order to show the appropriate loading state.
    * For more details on Suspense, see our [Loading States with Suspense](../../guided-tour/rendering/loading-states/) guide.
* The component is automatically subscribed to updates to the query data: if the data for this query is updated anywhere in the app, the component will automatically re-render with the latest updated data.
* After a component using `useLazyLoadQuery` has committed, re-rendering/updating the component will not cause the query to be fetched again.
    * If the component is re-rendered with *different query variables,* that will cause the query to be fetched again with the new variables, and potentially re-render with different data.
    * If the component *unmounts and remounts*, that will cause the current query and variables to be refetched (depending on the `fetchPolicy` and the state of the cache).

### Differences with `QueryRenderer`

* `useLazyLoadQuery` no longer takes a Relay environment as a parameter, and thus no longer sets the environment in React Context, like `QueryRenderer` did. Instead, `useLazyLoadQuery` should be used as a descendant of a [`RelayEnvironmentProvider`](../relay-environment-provider), which now sets the Relay environment in Context. Usually, you should render a single `RelayEnvironmentProvider` at the very root of the application, to set a single Relay environment for the whole application.
* `useLazyLoadQuery` will use [Suspense](../../guided-tour/rendering/loading-states) to allow developers to render loading states using Suspense boundaries, and will throw errors if network errors occur, which can be caught and rendered with Error Boundaries. This as opposed to providing error objects or null props to the `QueryRenderer` render function to indicate errors or loading states.
* `useLazyLoadQuery` fully supports fetch policies in order to reuse data that is cached in the Relay store instead of solely relying on the network response cache.
* `useLazyLoadQuery` has better type safety guarantees for the data it returns, which was not possible with QueryRenderer since we couldn't parametrize the type of the data with a renderer api.

---

### Api Reference Hooks Load Query (`website/docs/api-reference/hooks/load-query.mdx`)

---
id: load-query
title: loadQuery
slug: /api-reference/load-query/
description: API reference for loadQuery, which imperatively fetches data for a query, retains that query and returns a query reference
keywords:
  - preload
  - fetch
  - query
  - render-as-you-fetch
  - retain
  - query reference
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## `loadQuery`

This function is designed to be used with the `usePreloadedQuery()` hook to implement the "render-as-you-fetch".

Query references returned from `loadQuery` will leak data into the Relay store if `.dispose()` is not called on them once they are no longer referenced. As such, prefer calling `useQueryLoader` when possible, which ensures that query references are disposed for you.

See the [`usePreloadedQuery`](../use-preloaded-query) docs for a more complete example.

```js
const MyEnvironment = require('MyEnvironment');
const {loadQuery} = require('react-relay');

const query = graphql`
  query AppQuery($id: ID!) {
    user(id: $id) {
      name
    }
  }
`;

// Note: you should generally not call loadQuery at the top level.
// Instead, it should be called in response to an event (such a route navigation,
// click, etc.).
const queryReference = loadQuery(
  MyEnvironment,
  query,
  {id: '4'},
  {fetchPolicy: 'store-or-network'},
);

// later: pass queryReference to usePreloadedQuery()
// Note that query reference should have .dispose() called on them,
// which is missing in this example.
```

### Arguments

* `environment`: A Relay Environment instance on which to execute the request. If you're starting this request somewhere within a React component, you probably want to use the environment you obtain from using [`useRelayEnvironment`](#userelayenvironment).
* `query`: GraphQL query to fetch, specified using a `graphql` template literal, or a preloadable concrete request, which can be acquired by requiring the file `<name-of-query>$Parameters.graphql`. Relay will only generate the `$Parameters` file if the query is annotated with `@preloadable`.
* `variables`: Object containing the variable values to fetch the query. These variables need to match GraphQL variables declared inside the query.
* `options`: *_[Optional]_* options object
    * `fetchPolicy`: Determines if cached data should be used, and whether to send a network request based on the cached data that is currently available in the Relay store (for more details, see our [Fetch Policies](../../guided-tour/reusing-cached-data/fetch-policies) and [Garbage Collection](../../guided-tour/reusing-cached-data/presence-of-data) guides):
        * "store-or-network": **(default)** *will* reuse locally cached data and will *only* send a network request if any data for the query is missing. If the query is fully cached, a network request will *not* be made.
        * "store-and-network": *will* reuse locally cached data and will *always* send a network request, regardless of whether any data was missing from the local cache or not.
        * "network-only": *will not* reuse locally cached data, and will *always* send a network request to fetch the query, ignoring any data that might be locally cached in Relay.
    * `networkCacheConfig`: *_[Optional]_* Default value: `{force: true}`. Object containing cache config options for the *network layer*. Note that the network layer may contain an *additional* query response cache which will reuse network responses for identical queries. If you want to bypass this cache completely (which is the default behavior), pass `{force: true}` as the value for this option.
* `environmentProviderOptions`: *[Optional]* options object
    * Options passed to an `environmentProvider` used in `prepareSurfaceEntryPoint.js`.

### Return Value

A query reference with the following properties:

* `dispose`: a method that will release the query reference from being retained by the store. This can cause the data referenced by the query reference to be garbage collected.

The exact format of the return value is *unstable and highly likely to change*. We strongly recommend not using any other properties of the return value, as such code would be highly likely to break when upgrading to future versions of Relay. Instead, pass the result of `loadQuery()` to `usePreloadedQuery()`.

### Behavior

* `loadQuery()` will fetch data if passed a query, or data and the query if passed a preloadable concrete request. Once both the query and data are available, the data from the query will be written to the store. This differs from the behavior of `preloadQuery_DEPRECATED`, which would only write data to the store if the query was passed to `usePreloadedQuery`.
* the query reference returned from `loadQuery` will be retained by the Relay store, preventing the data from being garbage collected. Once you call `.dispose()` on the query reference, it can be garbage collected.
* `loadQuery()` will throw an error if it is called during React's render phase.




<DocsRating />

---

### Api Reference Hooks Relay Environment Provider (`website/docs/api-reference/hooks/relay-environment-provider.mdx`)

---
id: relay-environment-provider
title: RelayEnvironmentProvider
slug: /api-reference/relay-environment-provider/
description: API reference for RelayEnvironmentProvider, which sets a Relay environment in React context
keywords:
  - environment
  - context
---

import DocsRating from '@site/src/core/DocsRating';

## `RelayEnvironmentProvider`

This component is used to set a Relay environment in React Context. Usually, a *single* instance of this component should be rendered at the very root of the application, in order to set the Relay environment for the whole application:

```js
const React = require('React');
const {
  Store,
  RecordSource,
  Environment,
  Network,
  Observable,
} = require("relay-runtime");

const {RelayEnvironmentProvider} = require('react-relay');

/**
 * Custom fetch function to handle GraphQL requests for a Relay environment.
 *
 * This function is responsible for sending GraphQL requests over the network and returning
 * the response data. It can be customized to integrate with different network libraries or
 * to add authentication headers as needed.
 *
 * @param {RequestParameters} params - The GraphQL request parameters to send to the server.
 * @param {Variables} variables - Variables used in the GraphQL query.
 */
function fetchFunction(params, variables) {
  const response = fetch("http://my-graphql/api", {
    method: "POST",
    headers: [["Content-Type", "application/json"]],
    body: JSON.stringify({
      query: params.text,
      variables,
    }),
  });

  return Observable.from(response.then((data) => data.json()));
};

/**
 * Creates a new Relay environment instance for managing (fetching, storing) GraphQL data.
 */
function createEnvironment() {
  const network = Network.create(fetchFunction);
  const store = new Store(new RecordSource());
  return new Environment({ store, network });
}

const environment = createEnvironment();

function Root() {
  return (
    <RelayEnvironmentProvider environment={environment}>
      <App />
    </RelayEnvironmentProvider>
  );
}

module.exports = Root;
```

### Props

* `environment`: The Relay environment to set in React Context. Any Relay Hooks (like [`useLazyLoadQuery`](../use-lazy-load-query) or [`useFragment`](../use-fragment)) used in descendants of this provider component will use the Relay environment specified here

<DocsRating/>

---

### Api Reference Hooks Use Client Query (`website/docs/api-reference/hooks/use-client-query.mdx`)

---
id: use-client-query
title: useClientQuery
slug: /api-reference/use-client-query/
description: API reference for useClientQuery, a React hook used to render client only queries
keywords:
  - query
  - read
  - client-query
---

import DocsRating from '@site/src/core/DocsRating';

`useClientQuery` hook is used to render queries that read _only_ client fields.

The Relay Compiler fully supports [client-side extensions](../../guides/client-schema-extensions/) of the schema, which allows you to define local fields and types.

```graphql
# example client extension of the `Query` type
extend type Query {
  client_field: String
}
```

These client-only fields are not sent to the server, and should be updated
using APIs for local updates, for example `commitPayload`.

```js
const React = require('React');

const {graphql, useClientQuery} = require('react-relay');

function ClientQueryComponent() {
  const data = useClientQuery(
    graphql`
      query ClientQueryComponentQuery {
        client_field
      }
    `,
    {}, // variables
  );

  return (
    <div>{data.client_field}</div>
  );
}
```


### Arguments

* `query`: GraphQL query specified using a `graphql` template literal.
* `variables`: Object containing the variable values to fetch the query. These variables need to match GraphQL variables declared inside the query.

### Return Value

* `data`: Object that contains data which has been read out from the Relay store; the object matches the shape of specified query.
    * The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema. For example, the type of `data` above is: `{| user: ?{| name: ?string |} |}`.

### Behavior

* This hooks works as [`useLazyLoadQuery`](../use-lazy-load-query) with `fetchPolicy: store-only`, it does not send the network request.


<DocsRating />

---

### Api Reference Hooks Use Fragment (`website/docs/api-reference/hooks/use-fragment.mdx`)

---
id: use-fragment
title: useFragment
slug: /api-reference/use-fragment/
description: API reference for useFragment, a React hook used to read fragment data from the Relay store using a fragment reference
keywords:
  - fragment
  - read
  - fragment reference
---

import DocsRating from '@site/src/core/DocsRating';

## `useFragment`

```js
import type {UserComponent_user$key} from 'UserComponent_user.graphql';

const React = require('React');

const {graphql, useFragment} = require('react-relay');

type Props = {
  user: UserComponent_user$key,
};

function UserComponent(props: Props) {
  const data = useFragment(
    graphql`
      fragment UserComponent_user on User {
        name
        profile_picture(scale: 2) {
          uri
        }
      }
    `,
    props.user,
  );

  return (
    <>
      <h1>{data.name}</h1>
      <div>
        <img src={data.profile_picture?.uri} />
      </div>
    </>
  );
}
```

### Arguments

* `fragment`: GraphQL fragment specified using a `graphql` template literal.
* `fragmentReference`: The *fragment reference* is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from.
    * The type of the fragment reference can be imported from the generated Flow types, from the file `<fragment_name>.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `<fragment_name>$key`. We use our [lint rule](https://github.com/relayjs/eslint-plugin-relay) to enforce that the type of the fragment reference prop is correctly declared.

### Return Value

* `data`: Object that contains data which has been read out from the Relay store; the object matches the shape of specified fragment.
    * The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema. For example, the type of `data` above is: `{ name: ?string, profile_picture: ?{ uri: ?string } }`.

### Behavior

* The component is automatically subscribed to updates to the fragment data: if the data for this particular `User` is updated anywhere in the app (e.g. via fetching new data, or mutating existing data), the component will automatically re-render with the latest updated data.
* The component will suspend if any data for that specific fragment is missing, and the data is currently being fetched by a parent query.
    * For more details on Suspense, see our [Loading States with Suspense](../../guided-tour/rendering/loading-states) guide.


<DocsRating />

---

### Api Reference Hooks Use Lazy Load Query (`website/docs/api-reference/hooks/use-lazy-load-query.mdx`)

---
id: use-lazy-load-query
title: useLazyLoadQuery
slug: /api-reference/use-lazy-load-query/
description: API reference for useLazyLoadQuery, a React hook used to lazily fetch query data when a component renders
keywords:
  - lazy fetching
  - query
  - fetch
---

import DocsRating from '@site/src/core/DocsRating';

## `useLazyLoadQuery`

Hook used to fetch a GraphQL query during render. This hook can trigger multiple nested or waterfalling round trips if used without caution, and waits until render to start a data fetch (when it can usually start a lot sooner than render), thereby degrading performance. Instead, prefer [`usePreloadedQuery`](../use-preloaded-query).

```js
const React = require('React');

const {graphql, useLazyLoadQuery} = require('react-relay');

function App() {
  const data = useLazyLoadQuery(
    graphql`
      query AppQuery($id: ID!) {
        user(id: $id) {
          name
        }
      }
    `,
    {id: 4},
    {fetchPolicy: 'store-or-network'},
  );

 return <h1>{data.user?.name}</h1>;
}
```

### Arguments

* `gqlQuery`: GraphQL query specified using a `graphql` template literal.
* `variables`: Object containing the variable values to fetch the query. These variables need to match GraphQL variables declared inside the query.
* `options`: _*[Optional]*_ options object
  * `fetchPolicy`: _*[Optional]*_ Determines if cached data should be used, and when to send a network request based on the cached data that is currently available in the Relay store (for more details, see our [Fetch Policies](../../guided-tour/reusing-cached-data/fetch-policies) and [Garbage Collection](../../guided-tour/reusing-cached-data/presence-of-data) guides):
     * "store-or-network": _*(default)*_ *will* reuse locally cached data and will *only* send a network request if any data for the query is missing. If the query is fully cached, a network request will *not* be made.
     * "store-and-network": *will* reuse locally cached data and will *always* send a network request, regardless of whether any data was missing from the local cache or not.
     * "network-only": *will* *not* reuse locally cached data, and will *always* send a network request to fetch the query, ignoring any data that might be locally cached in Relay.
     * "store-only": *will* *only* reuse locally cached data, and will *never* send a network request to fetch the query. In this case, the responsibility of fetching the query falls to the caller, but this policy could also be used to read and operate on data that is entirely [local](../../guided-tour/updating-data/local-data-updates).
  * `fetchKey`: _*[Optional]*_ A `fetchKey` can be passed to force a re-evaluation of the current query and variables when the component re-renders, even if the variables didn't change, or even if the component isn't remounted (similarly to how passing a different `key` to a React component will cause it to remount). If the `fetchKey` is different from the one used in the previous render, the current query will be re-evaluated against the store, and it might be refetched depending on the current `fetchPolicy` and the state of the cache.
  * `networkCacheConfig`: _*[Optional]*_ Default value: `{force: true}`. Object containing cache config options for the *network layer*. Note that the network layer may contain an *additional* query response cache which will reuse network responses for identical queries. If you want to bypass this cache completely (which is the default behavior), pass `{force: true}` as the value for this option.
  * `UNSTABLE_renderPolicy`: _*[Optional]*_ Undocumented option.

### Return Value

- `data`: Object that contains data which has been read out from the Relay store; the object matches the shape of specified query.
  - The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema. For example, the type of `data` above is: `{| user: ?{| name: ?string |} |}`.

import UseLazyLoadQueryExtra from './_use-lazy-load-query-extra.mdx';

<UseLazyLoadQueryExtra />
<DocsRating />

---

### Api Reference Hooks Use Mutation (`website/docs/api-reference/hooks/use-mutation.mdx`)

---
id: use-mutation
title: useMutation
slug: /api-reference/use-mutation/
description: API reference for useMutation, a React hook used to execute a GraphQL mutation
keywords:
  - mutation
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
// @fb-only

## `useMutation`

Hook used to execute a mutation in a React component.

```js
import type {FeedbackLikeMutation} from 'FeedbackLikeMutation.graphql';
const React = require('React');

const {graphql, useMutation} = require('react-relay');

function LikeButton() {
  const [commit, isInFlight] = useMutation<FeedbackLikeMutation>(graphql`
    mutation FeedbackLikeMutation($input: FeedbackLikeData!) {
      feedback_like(data: $input) {
        feedback {
          id
          viewer_does_like
          like_count
        }
      }
    }
  `);

  if (isInFlight) {
    return <Spinner />;
  }

  return (
    <button
      onClick={() => {
        commit({
          variables: {
            input: {
              id: '123',
              text: 'text',
            },
          },
          onCompleted(data) {
            console.log(data);
          },
        });
      }}
    />
  );
}
```

### Arguments

* `mutation`: GraphQL mutation specified using a `graphql` template literal.

<OssOnly>

* `commitMutationFn`: `<T: MutationParameters>(IEnvironment, MutationConfig<T>): Disposable`. *_[Optional]_* A function with the same signature as [`commitMutation`](../commit-mutation), which will be called in its stead. Defaults to `commitMutation`.

</OssOnly>

// @fb-only

### Return Value

Tuple containing the following values:

* [0] `commitMutation`: The function that will execute the mutation
    * Arguments, the syntax signature is almost the same as our `commitMutation` API
        * `variables`: Object containing the variables needed for the mutation. For example, if the mutation defines an `$input` variable, this object should contain an `input` key, whose shape must match the shape of the data expected by the mutation as defined by the GraphQL schema.
        * `onCompleted`: Callback function executed when the request is completed and the in-memory Relay store is updated with the `updater` function. Takes a `response` object, which is the "raw" server response. Internally `errors` are not allowed, `CRITICAL` error will be thrown in the `onError` handler.
        * `onError`: Callback function executed if Relay encounters an error during the request. Internally, `CRITICAL` error during reading the mutation result on the server
        * `optimisticResponse`: Object containing the data to optimistically update the local in-memory store, i.e. immediately, before the mutation request has completed. This object must have the same shape as the mutation's response type, as defined by the GraphQL schema. If provided, Relay will use the `optimisticResponse` data to update the fields on the relevant records in the local data store, *before* `optimisticUpdater` is executed. If an error occurs during the mutation request, the optimistic update will be rolled back.
        * `optimisticUpdater`: Function used to optimistically update the local in-memory store, i.e. immediately, before the mutation request has completed. If an error occurs during the mutation request, the optimistic update will be rolled back. This function takes a `store`, which is a proxy of the in-memory [Relay Store](../store/). In this function, the client defines how to update the local data via the `store` instance. For details on how to use the `store`, please refer to our [Relay Store API Reference](../store/). Please note:
            * It is usually preferable to just pass an `optimisticResponse` option instead of an `optimisticUpdater`, unless you need to perform updates on the local records that are more complicated than just updating fields (e.g. deleting records or adding items to collections).
            * If you do decide to use an `optimisticUpdater`, often times it can be the same function as `updater`.
        * `updater`: Function used to update the local in-memory store based on the real server response from the mutation. If `updater` is not provided, by default, Relay will know to automatically update the fields on the records referenced in the mutation response; however, you should pass an `updater` if you need to make more complicated updates than just updating fields (e.g. deleting records or adding items to collections). When the server response comes back, Relay first reverts any changes introduced by `optimisticUpdater` or `optimisticResponse` and will then execute `updater`. This function takes a `store`, which is a proxy of the in-memory [Relay Store](../store/). In this function, the client defines how to update the local data based on the server response via the `store` instance. For details on how to use the `store`, please refer to our [Relay Store API](../store/)
        * `uploadables`: An optional uploadable map, an object representing any number of uploadable items, with one key per item. Each value must be of type `File` or `Blob`.
        *  No environment argument: `useMutation` will automatically use the current environment provided by `RelayEnvironmentProvider`
    * Return value:
        * `disposable`: Object containing a `dispose` function. Calling `disposable.dispose()` will revert the optimistic update, and Relay won't update the store or call any success/error callback, but the network request is not guaranteed to be cancelled. If the `dispose` is called after the mutation has succeeded, it will not rollback the update in Relay store.
* [1] `areMutationsInFlight`: Will be `true` if any mutation triggered by calling `commitMutation` is still in flight. If you call `commitMutation` multiple times, there can be multiple mutations in flight at once.


<DocsRating />

---

### Api Reference Hooks Use Pagination Fragment (`website/docs/api-reference/hooks/use-pagination-fragment.mdx`)

---
id: use-pagination-fragment
title: usePaginationFragment
slug: /api-reference/use-pagination-fragment/
description: API reference for usePaginationFragment, a React hook used to paginate a connection
keywords:
  - pagination
  - connection
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
// @fb-only
import {default as FbUsePaginationFragmentReturnValue} from '../../FbFakeContent.mdx'; // @oss-only

## `usePaginationFragment`

You can use `usePaginationFragment` to render a fragment that uses a `@connection` and paginate over it:

```js
import type {FriendsList_user$key} from 'FriendsList_user.graphql';

const React = require('React');

const {graphql, usePaginationFragment} = require('react-relay');

type Props = {
  user: FriendsList_user$key,
};

function FriendsList(props: Props) {
  const {
    data,
    loadNext,
    loadPrevious,
    hasNext,
    hasPrevious,
    isLoadingNext,
    isLoadingPrevious,
    refetch, // For refetching connection
  } = usePaginationFragment(
    graphql`
      fragment FriendsListComponent_user on User
      @argumentDefinitions(
        count: { type: "Int", defaultValue: 5 }
        cursor: { type: "String" }
      )
      @refetchable(queryName: "FriendsListPaginationQuery") {
        name
        friends(first: $count, after: $cursor)
        @connection(key: "FriendsList_user_friends") {
          edges {
            node {
              name
              age
            }
          }
        }
      }
    `,
    props.user,
  );

  return (
    <>
      <h1>Friends of {data.name}:</h1>

      <List items={data.friends?.edges.map(edge => edge.node)}>
        {node => {
          return (
            <div>
              {node.name} - {node.age}
            </div>
          );
        }}
      </List>
      <Button onClick={() => loadNext(10)}>Load more friends</Button>
    </>
  );
}

module.exports = FriendsList;
```

### Arguments

* `fragment`: GraphQL fragment specified using a `graphql` template literal.
    * This fragment must have an `@connection` directive on a connection field, otherwise using it will throw an error.
    * This fragment must have a `@refetchable` directive, otherwise using it will throw an error. The `@refetchable` directive can only be added to fragments that are "refetchable", that is, on fragments that are declared on `Viewer` or  `Query` types, or on a type that implements `Node` (i.e. a type that has an `id`).
        * Note that you *do not* need to manually specify a pagination query yourself. The `@refetchable` directive will autogenerate a query with the specified `queryName`. This will also generate Flow types for the query, available to import from the generated file: `<queryName>.graphql.js`.
* `fragmentReference`: The *fragment reference* is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from.
    * The type of the fragment reference can be imported from the generated Flow types, from the file `<fragment_name>.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `<fragment_name>$key`. We use our [lint rule](https://github.com/relayjs/eslint-plugin-relay) to enforce that the type of the fragment reference prop is correctly declared.

### Return Value

<FbInternalOnly>
  <FbUsePaginationFragmentReturnValue />
</FbInternalOnly>

<OssOnly>

Object containing the following properties:

* `data`: Object that contains data which has been read out from the Relay store; the object matches the shape of specified fragment.
    * The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema.
* `isLoadingNext`: Boolean value which indicates if a pagination request for the *next* items in the connection is currently in flight, including any incremental data payloads.
* `isLoadingPrevious`: Boolean value which indicates if a pagination request for the *previous* items in the connection is currently in flight, including any incremental data payloads.
* `hasNext`: Boolean value which indicates if the end of the connection has been reached in the "forward" direction. It will be true if there are more items to query for available in that direction, or false otherwise.
* `hasPrevious`: Boolean value which indicates if the end of the connection has been reached in the "backward" direction. It will be true if there are more items to query for available in that direction, or false otherwise.
* `loadNext`: Function used to fetch more items in the connection in the "forward" direction.
    * Arguments:
        * `count`*:* Number that indicates how many items to query for in the pagination request.
        * `options`: *_[Optional]_* options object
            * `onComplete`: Function that will be called whenever the refetch request has completed, including any incremental data payloads. If an error occurs during the request, `onComplete` will be called with an `Error` object as the first parameter.
    * Return Value:
        * `disposable`: Object containing a `dispose` function. Calling `disposable.dispose()` will cancel the pagination request.
    * Behavior:
        * Calling `loadNext`  *will not* cause the component to suspend. Instead, the `isLoadingNext` value will be set to true while the request is in flight, and the new items from the pagination request will be added to the connection, causing the component to re-render.
        * Pagination requests initiated from calling `loadNext` will *always* use the same variables that were originally used to fetch the connection, *except* pagination variables (which need to change in order to perform pagination); changing variables other than the pagination variables during pagination doesn't make sense, since that'd mean we'd be querying for a different connection.
* `loadPrevious`: Function used to fetch more items in the connection in the "backward" direction.
    * Arguments:
        * `count`*:* Number that indicates how many items to query for in the pagination request.
        * `options`: *_[Optional]_* options object
            * `onComplete`: Function that will be called whenever the refetch request has completed, including any incremental data payloads. If an error occurs during the request, `onComplete` will be called with an `Error` object as the first parameter.
    * Return Value:
        * `disposable`: Object containing a `dispose` function. Calling `disposable.dispose()` will cancel the pagination request.
    * Behavior:
        * Calling `loadPrevious`  *will not* cause the component to suspend. Instead, the `isLoadingPrevious` value will be set to true while the request is in flight, and the new items from the pagination request will be added to the connection, causing the component to re-render.
        * Pagination requests initiated from calling `loadPrevious` will *always* use the same variables that were originally used to fetch the connection, *except* pagination variables (which need to change in order to perform pagination); changing variables other than the pagination variables during pagination doesn't make sense, since that'd mean we'd be querying for a different connection.
* `refetch`: Function used to refetch the connection fragment with a potentially new set of variables.
    * Arguments:
        * `variables`: Object containing the new set of variable values to be used to fetch the `@refetchable` query.
            * These variables need to match GraphQL variables referenced inside the fragment.
            * However, only the variables that are intended to change for the refetch request need to be specified; any variables referenced by the fragment that are omitted from this input will fall back to using the value specified in the original parent query. So for example, to refetch the fragment with the exact same variables as it was originally fetched, you can call `refetch({})`.
            * Similarly, passing an `id` value for the `$id` variable is _*optional*_, unless the fragment wants to be refetched with a different `id`. When refetching a `@refetchable` fragment, Relay will already know the id of the rendered object.
        * `options`: *_[Optional]_* options object
            * `fetchPolicy`: Determines if cached data should be used, and when to send a network request based on cached data that is available. See the [Fetch Policies](../../guided-tour/reusing-cached-data/fetch-policies/) section for full specification.
            * `onComplete`: Function that will be called whenever the refetch request has completed, including any incremental data payloads.
    * Return value:
        * `disposable`: Object containing a `dispose` function. Calling `disposable.dispose()` will cancel the refetch request.
    * Behavior:
        * Calling `refetch` with a new set of variables will fetch the fragment again *with the newly provided variables*. Note that the variables you need to provide are only the ones referenced inside the fragment. In this example, it means fetching the translated body of the currently rendered Comment, by passing a new value to the `lang` variable.
        * Calling `refetch` will re-render your component and may cause it to *[suspend](../../guided-tour/rendering/loading-states)*, depending on the specified `fetchPolicy` and whether cached data is available or if it needs to send and wait for a network request. If refetch causes the component to suspend, you'll need to make sure that there's a `Suspense` boundary wrapping this component.
        * For more details on Suspense, see our [Loading States with Suspense](../../guided-tour/rendering/loading-states/) guide.

</OssOnly>

### Behavior

* The component is automatically subscribed to updates to the fragment data: if the data for this particular `User` is updated anywhere in the app (e.g. via fetching new data, or mutating existing data), the component will automatically re-render with the latest updated data.
* The component will suspend if any data for that specific fragment is missing, and the data is currently being fetched by a parent query.
    * For more details on Suspense, see our [Loading States with Suspense](../../guided-tour/rendering/loading-states/) guide.
* Note that pagination (`loadNext` or `loadPrevious`), *will not* cause the component to suspend.

### Differences with `PaginationContainer`

* A pagination query no longer needs to be specified in this api, since it will be automatically generated by Relay by using a `@refetchable` fragment.
* This api supports simultaneous bi-directional pagination out of the box.
* This api no longer requires passing `getVariables` or `getFragmentVariables` configuration functions, like the `PaginationContainer` does.
    * This implies that pagination no longer has a distinction between `variables` and `fragmentVariables`, which were previously vaguely defined concepts. Pagination requests will always use the same variables that were originally used to fetch the connection, *except* pagination variables (which need to change in order to perform pagination); changing variables other than the pagination variables during pagination doesn't make sense, since that'd mean we'd be querying for a different connection.
* This api no longer takes additional configuration like `direction` or `getConnectionFromProps` function (like Pagination Container does). These values will be automatically determined by Relay.
* Refetching no longer has a distinction between `variables` and `fragmentVariables`, which were previously vaguely defined concepts. Refetching will always correctly refetch and render the fragment with the variables you provide (any variables omitted in the input will fallback to using the original values in the parent query).
* Refetching will unequivocally update the component, which was not always true when calling `refetchConnection` from `PaginationContainer` (it would depend on what you were querying for in the refetch query and if your fragment was defined on the right object type).


<DocsRating />

---

### Api Reference Hooks Use Prefetchable Forward Pagination Fragment (`website/docs/api-reference/hooks/use-prefetchable-forward-pagination-fragment.mdx`)

---
id: use-prefetchable-forward-pagination-fragment
title: usePrefetchableForwardPaginationFragment
slug: /api-reference/use-prefetchable-forward-pagination-fragment/
description: API reference for usePrefetchableForwardPaginationFragment, an experimental React hook used to paginate a connection and automatically prefetches
keywords:
  - pagination
  - connection
  - prefetching
---

import DocsRating from '@site/src/core/DocsRating';

NOTE: This is an experimental API and may be subject to change.
`usePrefetchableForwardPaginationFragment` is similar to [`usePaginationFragment`](../use-pagination-fragment). It adds the capability to automatically prefetch a `bufferSize` number of items to fill the buffer without displaying the items. And when `loadNext` is called, it vends from the buffer first to achieve faster pagination. It only supports forward pagination (provides APIs for `loadNext`, `hasNext` and `isLoadingNext`) for now.

```js
import type {FriendsList_user$key} from 'FriendsList_user.graphql';

const React = require('React');

const {graphql, usePrefetchableForwardPaginationFragment} = require('react-relay');

type Props = {
  user: FriendsList_user$key,
};

function FriendsList(props: Props) {
  const {
    data,
    edges, // NOTE: It is required to use `edges` to access the items
    loadNext,
    hasNext,
    isLoadingNext,
    refetch, // For refetching connection
  } = usePrefetchableForwardPaginationFragment(
    graphql`
      fragment FriendsListComponent_user on User
      @refetchable(queryName: "FriendsListPaginationQuery") {
        name
        friends(first: $count, after: $cursor)
        @connection(key: "FriendsList_user_friends", prefetchable_pagination: true) {
          edges {
            node {
              name
              age
            }
          }
        }
      }
    `,
    props.user,
  );

  return (
    <>
      <h1>Friends of {data.name}:</h1>

      <List items={edges.map(edge => edge.node)}>
        {node => {
          return (
            <div>
              {node.name} - {node.age}
            </div>
          );
        }}
      </List>
      <Button onClick={() => loadNext(10)}>Load more friends</Button>
    </>
  );
}

module.exports = FriendsList;
```

### Arguments

* `fragment`: GraphQL fragment specified using a `graphql` template literal.
    * This fragment must have an `@connection` directive on a connection field, and set `prefetchable_pagination` to `true`, otherwise using it will throw an error.
    * This fragment must have a `@refetchable` directive, otherwise using it will throw an error. The `@refetchable` directive can only be added to fragments that are "refetchable", that is, on fragments that are declared on `Viewer` or  `Query` types, or on a type that implements `Node` (i.e. a type that has an `id`).
        * Note that you *do not* need to manually specify a pagination query yourself. The `@refetchable` directive will autogenerate a query with the specified `queryName`. This will also generate Flow types for the query, available to import from the generated file: `<queryName>.graphql.js`.
* `fragmentReference`: The *fragment reference* is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from.
    * The type of the fragment reference can be imported from the generated Flow types, from the file `<fragment_name>.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `<fragment_name>$key`. We use our [lint rule](https://github.com/relayjs/eslint-plugin-relay) to enforce that the type of the fragment reference prop is correctly declared.
* `bufferSize`: The size of the buffer. The component will always try to prefetch to fill the buffer.
* `initialSize`: *_[Optional]_* argument to define the initial number of items to display. If it is unset, the component shows all available items on the initial render or on refetch.
* `prefetchingLoadMoreOptions`: *_[Optional]_* fetching arguments to provide to the automatic prefetch.
  * `options`: *_[Optional]_* options object
      * `onComplete`: Function that will be called whenever the request has completed, including any incremental data payloads. If an error occurs during the request, `onComplete` will be called with an `Error` object as the first parameter.
* `minimalFetchSize`: Optional argument to define the minimum number of items to fetch in any requests.
* `disablePrefetching`: *_[Optional]_* boolean argument to disable the automatic prefetching that fills the buffer. When `true`, items are only fetched in response to explicit `loadNext` calls. Defaults to `false`.
* `maxFetchSize`: *_[Optional]_* argument to define the maximum number of items to fetch in any single request. Must be a positive integer. The number of items the hook computes for a request (either to fill the buffer or to fulfill a `loadNext`) is clamped to this value. This prevents the hook from generating large queries (for example, requesting close to the entire `totalCount` of a connection at once) that could overwhelm the backend. If unset (or not a positive number), no upper bound is applied.

### Return Value

Object containing the following properties:

* `edges`: The edges to use. This provides a filtered list of edges in the connection that excludes the buffer. Do not use the connection edges from `data` to render otherwise the hook will not work correctly.
* `data`: Object that contains data which has been read out from the Relay store; the object matches the shape of specified fragment.
    * The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema.
* `isLoadingNext`: Boolean value which indicates if a pagination request for the *next* items in the connection is currently in flight, including any incremental data payloads. The value stays `false` if the hook is automatically prefetching to fill the buffer, and the code hasn't asked for more items.
* `hasNext`: Boolean value which indicates if the end of the connection has been reached in the "forward" direction. It will be true if there are more items to query for available in that direction, or there are more items in the buffer, or false otherwise.
* `loadNext`: Function used to fetch more items in the connection in the "forward" direction.
    * Arguments:
        * `count`*:* Number that indicates how many items to show more from buffer or fetch.
        * `options`: *_[Optional]_* options object
            * `onComplete`: Function that will be called whenever the request has completed, including any incremental data payloads. If an error occurs during the request, `onComplete` will be called with an `Error` object as the first parameter.
    * Return Value: void
    * Behavior:
        * Calling `loadNext`  *will not* cause the component to suspend. The component first tries to fill the request using items prefetched in the buffer, if there aren't enough items, it sends a request. The `isLoadingNext` value will be set to true while the request is in flight.
        * Pagination requests initiated from calling `loadNext` will *always* use the same variables that were originally used to fetch the connection, *except* pagination variables (which need to change in order to perform pagination); changing variables other than the pagination variables during pagination doesn't make sense, since that'd mean we'd be querying for a different connection.

* `refetch`: Function used to refetch the connection fragment with a potentially new set of variables.
    * Arguments:
        * `variables`: Object containing the new set of variable values to be used to fetch the `@refetchable` query.
            * These variables need to match GraphQL variables referenced inside the fragment.
            * However, only the variables that are intended to change for the refetch request need to be specified; any variables referenced by the fragment that are omitted from this input will fall back to using the value specified in the original parent query. So for example, to refetch the fragment with the exact same variables as it was originally fetched, you can call `refetch({})`.
            * Similarly, passing an `id` value for the `$id` variable is _*optional*_, unless the fragment wants to be refetched with a different `id`. When refetching a `@refetchable` fragment, Relay will already know the id of the rendered object.
        * `options`: *_[Optional]_* options object
            * `fetchPolicy`: Determines if cached data should be used, and when to send a network request based on cached data that is available. See the [Fetch Policies](../../guided-tour/reusing-cached-data/fetch-policies/) section for full specification.
            * `onComplete`: Function that will be called whenever the refetch request has completed, including any incremental data payloads.
    * Return value:
        * `disposable`: Object containing a `dispose` function. Calling `disposable.dispose()` will cancel the refetch request.
    * Behavior:
        * Calling `refetch` with a new set of variables will fetch the fragment again *with the newly provided variables*. Note that the variables you need to provide are only the ones referenced inside the fragment. In this example, it means fetching the translated body of the currently rendered Comment, by passing a new value to the `lang` variable.
        * Calling `refetch` will re-render your component and may cause it to *[suspend](../../guided-tour/rendering/loading-states)*, depending on the specified `fetchPolicy` and whether cached data is available or if it needs to send and wait for a network request. If refetch causes the component to suspend, you'll need to make sure that there's a `Suspense` boundary wrapping this component.
        * For more details on Suspense, see our [Loading States with Suspense](../../guided-tour/rendering/loading-states/) guide.

### Behavior

* The component automatically fetches for more items to fill the buffer in `useEffect`.
* If a prefetch request errors, automatic prefetching is paused so the hook does not keep retrying against a failing server in a tight loop. Automatic prefetching resumes after the next explicit `loadNext` call or after a `refetch`.
* The component is automatically subscribed to updates to the fragment data: if the data for this particular `User` is updated anywhere in the app (e.g. via fetching new data, or mutating existing data), the component will automatically re-render with the latest updated data.
* The component will suspend if any data for that specific fragment is missing, and the data is currently being fetched by a parent query.
    * For more details on Suspense, see our [Loading States with Suspense](../../guided-tour/rendering/loading-states/) guide.
* Note that pagination (`loadNext`), *will not* cause the component to suspend.

<DocsRating />

---

### Api Reference Hooks Use Preloaded Query (`website/docs/api-reference/hooks/use-preloaded-query.mdx`)

---
id: use-preloaded-query
title: usePreloadedQuery
slug: /api-reference/use-preloaded-query/
description: API reference for usePreloadedQuery, a React hook used to read query data from the Relay store using a query reference
keywords:
  - read
  - query
  - query reference
---

import DocsRating from '@site/src/core/DocsRating';

## `usePreloadedQuery`

Hook used to access data fetched by an earlier call to [`loadQuery`](../load-query) or with the help of [`useQueryLoader`](../use-query-loader). This implements the "render-as-you-fetch" pattern:

* Call the `loadQuery` callback returned from `useQueryLoader`. This will store a query reference in React state.
    * You can also call the imported `loadQuery` directly, which returns a query reference. In that case, store the item in state or in a React ref, and call `dispose()` on the value when you are no longer using it.
* Then, in your render method, consume the query reference with `usePreloadedQuery()`. This call will suspend if the query is still pending, throw an error if it failed, and otherwise return the query results.
* This pattern is encouraged over `useLazyLoadQuery()` as it can allow fetching data earlier while not blocking rendering.

For more information, see the [Rendering Queries](../../guided-tour/rendering/queries) guide.

```js

import type {AppQueryType} from 'AppQueryType.graphql';

const React = require('React');

const {graphql, useQueryLoader, usePreloadedQuery} = require('react-relay');

const AppQuery = graphql`
  query AppQuery($id: ID!) {
    user(id: $id) {
      name
    }
  }
`;

type Props = {
  initialQueryRef: PreloadedQuery<AppQueryType>,
};

function NameLoader(props) {
  const [queryReference, loadQuery] = useQueryLoader(
    AppQuery,
    props.initialQueryRef, /* e.g. provided by router */
  );

  return (<>
    <Button
      onClick={() => loadQuery({id: '4'})}
      disabled={queryReference != null}
    >
      Reveal your name!
    </Button>
    <Suspense fallback="Loading...">
      {queryReference != null
        ? <NameDisplay queryReference={queryReference} />
        : null
      }
    </Suspense>
  </>);
}

function NameDisplay({ queryReference }) {
  const data = usePreloadedQuery(AppQuery, queryReference);

  return <h1>{data.user?.name}</h1>;
}
```

### Arguments

* `query`: GraphQL query specified using a `graphql` template literal.
* `preloadedQueryReference`: A `PreloadedQuery` query reference, which can be acquired from [`useQueryLoader`](../use-query-loader) or by calling [`loadQuery()`](../load-query) .

### Return Value

* `data`: Object that contains data which has been read out from the Relay store; the object matches the shape of specified query.
    * The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema. For example, the type of `data` above is: `{ user: ?{ name: ?string } }`.

<DocsRating />

---

### Api Reference Hooks Use Query Loader (`website/docs/api-reference/hooks/use-query-loader.mdx`)

---
id: use-query-loader
title: useQueryLoader
slug: /api-reference/use-query-loader/
description: API reference for useQueryLoader, a React hook used to imperatively fetch data for a query in response to a user event
keywords:
  - query
  - fetch
  - preload
  - render-as-you-fetch
---

import DocsRating from '@site/src/core/DocsRating';

## `useQueryLoader`

Hook used to make it easy to safely load and retain queries. It will keep a query reference stored in state, and dispose of it when the component is disposed or it is no longer accessible via state.

This hook is designed to be used with [`usePreloadedQuery`](../use-preloaded-query) to implement the "render-as-you-fetch" pattern. For more information, see the [Fetching Queries for Render](../../guided-tour/rendering/queries/) guide.

```js
import type {PreloadedQuery} from 'react-relay';

const {useQueryLoader, usePreloadedQuery} = require('react-relay');

const AppQuery = graphql`
  query AppQuery($id: ID!) {
    user(id: $id) {
      name
    }
  }
`;

function QueryFetcherExample() {
  const [
    queryReference,
    loadQuery,
    disposeQuery,
  ] = useQueryLoader(
    AppQuery,
  );

  if (queryReference == null) {
    return (
      <Button onClick={() => loadQuery({})}> Click to reveal the name </Button>
    );
  }

  return (
    <>
      <Button onClick={disposeQuery}>
        Click to hide the name and dispose the query.
      </Button>
      <React.Suspense fallback="Loading">
        <NameDisplay queryReference={queryReference} />
      </React.Suspense>
    </>
  );
}

function NameDisplay({ queryReference }) {
  const data = usePreloadedQuery(AppQuery, queryReference);

  return <h1>{data.user?.name}</h1>;
}
```

### Arguments

* `query`: GraphQL query specified using a `graphql` template literal.
* `initialQueryRef`: _*[Optional]*_ An initial `PreloadedQuery` to be used as the initial value of the `queryReference` stored in state and returned by `useQueryLoader`.

### Return value

A tuple containing the following values:

* `queryReference`: the query reference, or `null`.
* `loadQuery`: a callback that, when executed, will load a query, which will be accessible as `queryReference`. If a previous query was loaded, it will dispose of it. It should not be called during React's render phase.
    * Parameters
        * `variables`: the variables with which the query is loaded.
        * `options`: `LoadQueryOptions`. An optional options object, containing the following keys:
            * `fetchPolicy`: _*[Optional]*_ Determines if cached data should be used, and when to send a network request based on the cached data that is currently available in the Relay store (for more details, see our [Fetch Policies](../../guided-tour/reusing-cached-data/fetch-policies) and [Garbage Collection](../../guided-tour/reusing-cached-data/presence-of-data) guides):
                * "store-or-network": _*(default)*_ *will* reuse locally cached data and will *only* send a network request if any data for the query is missing. If the query is fully cached, a network request will *not* be made.
                * "store-and-network": *will* reuse locally cached data and will *always* send a network request, regardless of whether any data was missing from the local cache or not.
                * "network-only": *will* *not* reuse locally cached data, and will *always* send a network request to fetch the query, ignoring any data that might be locally cached in Relay.
            * `networkCacheConfig`: *_[Optional]_* Default value: `{force: true}`. Object containing cache config options for the *network layer*. Note that the network layer may contain an *additional* query response cache which will reuse network responses for identical queries. If you want to bypass this cache completely (which is the default behavior), pass `{force: true}` as the value for this option.
* `disposeQuery`: a callback that, when executed, will set `queryReference` to `null` and call `.dispose()` on it. It has type `() => void`. It should not be called during React's render phase.

### Behavior

* The `loadQuery` callback will fetch data if passed a query, or data and the query if passed a preloadable concrete request. Once both the query and data are available, the data from the query will be written to the store. This differs from the behavior of `preloadQuery_DEPRECATED`, which would only write data to the store if the query was passed to `usePreloadedQuery`.
* This query reference will be retained by the Relay store, preventing the data from being garbage collected. Once `.dispose()` is called on the query reference, the data is liable to be garbage collected.
* The `loadQuery` callback should not be called during React's render phase.

<DocsRating />

---

### Api Reference Hooks Use Refetchable Fragment (`website/docs/api-reference/hooks/use-refetchable-fragment.mdx`)

---
id: use-refetchable-fragment
title: useRefetchableFragment
slug: /api-reference/use-refetchable-fragment/
description: API reference for useRefetchableFragment, a React hook used to refetch fragment data
keywords:
  - refetch
  - fragment
---

import DocsRating from '@site/src/core/DocsRating';
import {FbInternalOnly, OssOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
// @fb-only
// @fb-only

## `useRefetchableFragment`

You can use `useRefetchableFragment` when you want to fetch and re-render a fragment with different data:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

```js
import type {CommentBody_comment$key} from 'CommentBody_comment.graphql';

const React = require('React');

const {graphql, useRefetchableFragment} = require('react-relay');


type Props = {
  comment: CommentBody_comment$key,
};

function CommentBody(props: Props) {
  const [data, refetch] = useRefetchableFragment(
    graphql`
      fragment CommentBody_comment on Comment
      @refetchable(queryName: "CommentBodyRefetchQuery") {
        body(lang: $lang) {
          text
        }
      }
    `,
    props.comment,
  );

  return (
    <>
      <p>{data.body?.text}</p>
      <Button
        onClick={() => {
          refetch({lang: 'SPANISH'}, {fetchPolicy: 'store-or-network'})
        }}
      >
        Translate Comment
      </Button>
    </>
  );
}

module.exports = CommentBody;
```

</OssOnly>

### Arguments

* `fragment`: GraphQL fragment specified using a `graphql` template literal. This fragment must have a `@refetchable` directive, otherwise using it will throw an error. The `@refetchable` directive can only be added to fragments that are "refetchable", that is, on fragments that are declared on `Viewer` or  `Query` types, or on a type that implements `Node` (i.e. a type that has an `id` and has the capability to be queried by its `id` field. See [graphql server specification section](../../guides/graphql-server-specification) for more details).
    * Note that you *do not* need to manually specify a refetch query yourself. The `@refetchable` directive will autogenerate a query with the specified `queryName`. This will also generate Flow types for the query, available to import from the generated file: `<queryName>.graphql.js`.
* `fragmentReference`: The *fragment reference* is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from.
    * The type of the fragment reference can be imported from the generated Flow types, from the file `<fragment_name>.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `<fragment_name>$key`. We use our [lint rule](https://github.com/relayjs/eslint-plugin-relay) to enforce that the type of the fragment reference prop is correctly declared.

### Return Value

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

Tuple containing the following values

* [0] `data`: Object that contains data which has been read out from the Relay store; the object matches the shape of specified fragment.
    * The Flow type for data will also match this shape, and contain types derived from the GraphQL Schema.
* [1] `refetch`: Function used to refetch the fragment with a potentially new set of variables.
    * Arguments:
        * `variables`: Object containing the new set of variable values to be used to fetch the `@refetchable` query.
            * These variables need to match GraphQL variables referenced inside the fragment.
            * If the fragment key passed to `useRefetchableFragment` is optional then all non-optional variables must be passed including, potentially, the object's ID since Relay may not have any existing variables to reuse.
            * If the fragment key is non-optional, only the variables that are intended to change for the refetch request need to be specified; any variables referenced by the fragment that are omitted from this input will fall back to using the value specified in the original parent query. So for example, to refetch the fragment with the exact same variables as it was originally fetched, you can call `refetch({})`.
            * Similarly, if the fragment key is non-optional, passing an `id` value for the `$id` variable is _*optional*_, unless the fragment wants to be refetched with a different `id`. When refetching a non-nullable `@refetchable` fragment, Relay will already know the id of the rendered object.
        * `options`: *_[Optional]_* options object
            * `fetchPolicy`: Determines if cached data should be used, and when to send a network request based on cached data that is available. See the [Fetch Policies](../../guided-tour/reusing-cached-data/fetch-policies/) section for full specification.
            * `onComplete`: Function that will be called whenever the refetch request has completed, including any incremental data payloads.
    * Return value:
        * `disposable`: Object containing a `dispose` function. Calling `disposable.dispose()` will cancel the refetch request.
    * Behavior:
        * Calling `refetch` with a new set of variables will fetch the fragment again *with the newly provided variables*. Note that the variables you need to provide are only the ones referenced inside the fragment. In this example, it means fetching the translated body of the currently rendered Comment, by passing a new value to the `lang` variable.
        * Calling `refetch` will re-render your component and may cause it to _*[suspend](../../guided-tour/rendering/loading-states)*_, depending on the specified `fetchPolicy` and whether cached data is available or if it needs to send and wait for a network request. If refetch causes the component to suspend, you'll need to make sure that there's a `Suspense` boundary wrapping this component.
        * For more details on Suspense, see our [Loading States with Suspense](../../guided-tour/rendering/loading-states/) guide.

</OssOnly>

### Behavior

* The component is automatically subscribed to updates to the fragment data: if the data for this particular `User` is updated anywhere in the app (e.g. via fetching new data, or mutating existing data), the component will automatically re-render with the latest updated data.
* The component will suspend if any data for that specific fragment is missing, and the data is currently being fetched by a parent query.
    * For more details on Suspense, see our [Loading States with Suspense](../../guided-tour/rendering/loading-states/) guide.

### Differences with `RefetchContainer`

* A refetch query no longer needs to be specified in this api, since it will be automatically generated by Relay by using a `@refetchable` fragment.
* Refetching no longer has a distinction between `refetchVariables` and `renderVariables`, which were previously vaguely defined concepts. Refetching will always correctly refetch and render the fragment with the variables you provide (any variables omitted in the input will fallback to using the original values from the parent query).
* Refetching will unequivocally update the component, which was not always true when calling refetch from `RefetchContainer` (it would depend on what you were querying for in the refetch query and if your fragment was defined on the right object type).



<DocsRating />

---

### Api Reference Hooks Use Relay Environment (`website/docs/api-reference/hooks/use-relay-environment.mdx`)

---
id: use-relay-environment
title: useRelayEnvironment
slug: /api-reference/use-relay-environment/
description: API reference for useRelayEnvironment, a React hook used to access the Relay environment from context
keywords:
  - environment
  - context
---

import DocsRating from '@site/src/core/DocsRating';

## `useRelayEnvironment`

Hook used to access a Relay environment that was set by a [`RelayEnvironmentProvider`](../relay-environment-provider):

```js
const React = require('React');

const {useRelayEnvironment} = require('react-relay');

function MyComponent() {
  const environment = useRelayEnvironment();

  const handler = useCallback(() => {
    // For example, can be used to pass the environment to functions
    // that require a Relay environment.
    commitMutation(environment, ...);
  }, [environment])

  return (...);
}

module.exports = MyComponent;
```

<DocsRating />

---

### Api Reference Hooks Use Subscription (`website/docs/api-reference/hooks/use-subscription.mdx`)

---
id: use-subscription
title: useSubscription
slug: /api-reference/use-subscription/
description: API reference for useSubscription, a React hook used to subscribe and unsubscribe from a subscription
keywords:
  - subscription
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
import GraphQLSubscriptionConfig from '../types/GraphQLSubscriptionConfig.mdx';

## `useSubscription`

Hook used to subscribe and unsubscribe to a subscription.

```js
import {graphql, useSubscription} from 'react-relay';
import {useMemo} from 'react';

const subscription = graphql`
  subscription UserDataSubscription($input: InputData!) {
    # ...
  }
`;

function UserComponent({ id }) {
  // IMPORTANT: your config should be memoized.
  // Otherwise, useSubscription will re-render too frequently.
  const config = useMemo(() => ({
    variables: {id},
    subscription,
  }), [id, subscription]);

  useSubscription(config);

  return (/* ... */);
}
```

### Arguments

* `config`: a memoized config of type [`GraphQLSubscriptionConfig`](#type-graphqlsubscriptionconfigtsubscriptionpayload) passed to [`requestSubscription`](../request-subscription/)
* `requestSubscriptionFn`: `?<TSubscriptionPayload>(IEnvironment, GraphQLSubscriptionConfig<TSubscriptionPayload>) => Disposable`. An optional function with the same signature as [`requestSubscription`](../request-subscription/), which will be called in its stead. Defaults to `requestSubscription`.

<GraphQLSubscriptionConfig />

### Behavior

* This is only a thin wrapper around the `requestSubscription` API. It will:
  * Subscribe when the component is mounted with the given config
  * Unsubscribe when the component is unmounted
  * Unsubscribe and resubscribe with new values if the environment, config or `requestSubscriptionFn` changes.
* If you have the need to do something more complicated, such as imperatively requesting a subscription, please use the [`requestSubscription`](../request-subscription/) API directly.
* See the [GraphQL Subscriptions Guide](../../guided-tour/updating-data/graphql-subscriptions/) for a more detailed explanation of how to work with subscriptions.

<FbInternalOnly>

:::note
`useSubscription` doesn't automatically add `client_subscription_id`. You may need to provide an arbitrary `client_subscription_id` to `config.variables.input`
:::

</FbInternalOnly>

<DocsRating />

---

### Api Reference Relay Resolvers Docblock Format (`website/docs/api-reference/relay-resolvers/docblock-format.mdx`)

---
id: docblock-format
title: 'Docblock Format'
slug: /api-reference/relay-resolvers/docblock-format/
description: Docblock format for Relay Resolvers
---
import {FbInternalOnly, fbContent} from 'docusaurus-plugin-internaldocs-fb/internal';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Relay Resolvers allow you to define additional types and fields in your GraphQL schema that are backed by client-side data. To achieve this, the Relay compiler looks for special `@relayType` and `@relayField` docblocks in your code. These docblocks define the types and fields in your schema and also tell Relay where to find the resolver functions that implement them.

For an overview of Relay Resolvers and how to think about them, see the [Relay Resolvers](../../guides/relay-resolvers/introduction.mdx) guide. This page documents the different docblock tags that the Relay compiler looks for, and how to use them.

:::note The Relay compiler only looks at docblocks which include the
`@relayType` or `@relayField` tag. Any other docblocks will be ignored.
:::

## `@relayType TypeName`

The `@relayType` tag followed by a single name defines a new GraphQL type in your schema. By default it is expected to be followed by an exported function whose name matches the type name. The function should accept an ID as its sole argument and return the JavaScript model/object which is the backing data for the type. See [`@weak`](#weak) for an alternative way to define the backing data for a type.

<Tabs
  groupId="resolver"
  defaultValue="Docblock"
  values={fbContent({
    internal: [
      {label: 'Docblock', value: 'Docblock'},
      {label: 'Flow', value: 'Flow'},
    ],
    external: [
      {label: 'Docblock', value: 'Docblock'},
    ]
  })}>
  <TabItem value="Docblock">

  ```tsx
  /**
   * @relayType User
   */
  export function User(id): UserModel {
    return UserModel.getById(id);
  }
  ```
  </TabItem>
  <TabItem value="Flow">

  ```tsx
  /**
   * @relayType
   */
  export function User(id): UserModel {
    return UserModel.getById(id);
  }
  ```
  </TabItem>
</Tabs>



See the [Defining Types](../../guides/relay-resolvers/defining-types.mdx) guide for more information.

## `@relayField TypeName.fieldName: FieldTypeName`

If the typename in a `@relayField` tag is followed by a dot and then a field definition, it defines a new field on the type. The portion following the `.` is expected to follow GraphQL's
[schema definition language](https://spec.graphql.org/June2018/#FieldDefinition).

Field definitions are expected to be followed by an exported function whose name matches the field name. The function should accept the model/object returned by the type resolver as its sole argument and return the value of the field.

<Tabs
  groupId="resolver"
  defaultValue="Docblock"
  values={fbContent({
    internal: [
      {label: 'Docblock', value: 'Docblock'},
      {label: 'Flow', value: 'Flow'},
    ],
    external: [
      {label: 'Docblock', value: 'Docblock'},
    ]
  })}>
  <TabItem value="Docblock">

  ```tsx
  /**
   * @relayField User.name: String
   */
  export function name(user: UserModel): string {
    return user.name;
  }
  ```
  </TabItem>
  <TabItem value="Flow">

  ```tsx
  /**
   * @relayType
   */
  export function name(user: UserModel): string {
    return user.name;
  }
  ```
  </TabItem>
</Tabs>

See the [Defining Fields](../../guides/relay-resolvers/defining-fields.mdx) guide for more information.

## `@rootFragment`

Relay Resolvers may also be used to model data that is derived from other data in the graph. These fields will be automatically recomputed by Relay when the data they depend on changes.

To define a derived field, use the `@rootFragment` tag on an existing field
definition, and follow it with the name of a fragment that defines the data that the field depends on. The resolver function for the field will be passed a fragment key which can be used to read the fragment data using `readFragment()`.

<Tabs
  groupId="resolver"
  defaultValue="Docblock"
  values={fbContent({
    internal: [
      {label: 'Docblock', value: 'Docblock'},
      {label: 'Flow', value: 'Flow'},
    ],
    external: [
      {label: 'Docblock', value: 'Docblock'},
    ]
  })}>
  <TabItem value="Docblock">

  ```tsx
  import {readFragment} from 'relay-runtime';

  /**
   * @relayField User.fullName: String
   * @rootFragment UserFullNameFragment
   */
  export function fullName(key: UserFullNameFragment$key): string {
    const user = readFragment(
      graphql`
        fragment UserFullNameFragment on User {
          firstName
          lastName
        }
      `,
      key,
    );
    return `${user.firstName} ${user.lastName}`;
  }
  ```
  </TabItem>
  <TabItem value="Flow">

  ```tsx
  import {readFragment} from 'relay-runtime';

  /**
   * @relayType
   */
  export function fullName(key: UserFullNameFragment$key): string {
    const user = readFragment(
      graphql`
        fragment UserFullNameFragment on User {
          firstName
          lastName
        }
      `,
      key,
    );
    return `${user.firstName} ${user.lastName}`;
  }
  ```
  </TabItem>
</Tabs>

See [Derived Fields](../../guides/relay-resolvers/derived-fields.mdx) for more information.

## `@live`

When modeling client state that can change over time, a resolver function which returns a single value is not sufficient. To accommodate this, Relay Resolvers allow you to define a field that returns a stream of values over time. This is done by adding the `@live` tag to a _field or type definition_.

`@live` resolvers must return an object with the shape of a `LiveStateValue` to allow Relay to read the current value and subscribe to changes.

<Tabs
  groupId="resolver"
  defaultValue="Docblock"
  values={fbContent({
    internal: [
      {label: 'Docblock', value: 'Docblock'},
      {label: 'Flow', value: 'Flow'},
    ],
    external: [
      {label: 'Docblock', value: 'Docblock'},
    ]
  })}>
  <TabItem value="Docblock">

  ```tsx
  import type {LiveState} from 'relay-runtime';

  /**
  * @relayField Query.counter: Int
  * @live
  */
  export function counter(): LiveState<number> {
    return {
      read: () => store.getState().counter,
      subscribe: cb => {
        return store.subscribe(cb);
      },
    };
  }
  ```
  </TabItem>
  <TabItem value="Flow">

  ```tsx
  import type {LiveState} from 'relay-runtime';

  /**
  * @relayType
  */
  export function counter(): LiveState<number> {
    return {
      read: () => store.getState().counter,
      subscribe: cb => {
        return store.subscribe(cb);
      },
    };
  }
  ```

  </TabItem>
</Tabs>

See the [Live Fields](../../guides/relay-resolvers/live-fields.mdx) guide for
more information.

## `@weak`

By default, Relay Resolvers expect the backing data for a type to be returned by a resolver function. However, in some cases objects of a given type may not have identifiers. In this case, you can use the `@relayType TypeName` syntax described above followed by the tag `@weak` to define a "weak" type.

Weak type declarations are expected to be followed by an exported type
definition whose name matches the type name.

<Tabs
  groupId="resolver"
  defaultValue="Docblock"
  values={fbContent({
    internal: [
      {label: 'Docblock', value: 'Docblock'},
      {label: 'Flow', value: 'Flow'},
    ],
    external: [
      {label: 'Docblock', value: 'Docblock'},
    ]
  })}>
  <TabItem value="Docblock">

  ```tsx
  /**
  * @relayType ProfilePicture
  * @weak
  */
  export type ProfilePicture = {
    url: string;
    width: number;
    height: number;
  };
  ```
  </TabItem>
  <TabItem value="Flow">

  ```tsx
  /**
  * @relayType
  */
  export type ProfilePicture = {
    url: string;
    width: number;
    height: number;
  };
  ```
  </TabItem>
</Tabs>

See the [Weak Types](../../guides/relay-resolvers/defining-types.mdx#Defining a “weak” type) guide for more information including how to define an edge to a weak type.

## `@deprecated`

Just like the GraphQL schema definition language, Relay Resolvers support the `@deprecated` tag to mark a field as deprecated. The tag may be followed by a string which will be used as the deprecation reason. Deprecated fields will
receive special treatment in the editor if you are using the
[Relay VSCode extension](../../editor-support.mdx).

```tsx
/**
 * @relayField User.name: String
 * @deprecated Use `fullName` instead.
 */
export function name(user: UserModel): string {
  return user.name;
}
```

See the [Deprecated](../../guides/relay-resolvers/deprecated.mdx) guide for more information.

## Descriptions

Any free text in the docblock (text not following a tag) will be used as the description for the type or field. This description will be surfaced in the editor if you are using the [Relay VSCode extension](../../editor-support.mdx).

```tsx
/**
 * @relayField User.name: String
 *
 * What's in a name? That which we call a rose by any other name would smell
 * just as sweet.
 */
export function name(user: UserModel): string {
  return user.name;
}
```

See the [Descriptions](../../guides/relay-resolvers/descriptions.mdx) guide for more information.

---

### Api Reference Relay Resolvers Runtime Functions (`website/docs/api-reference/relay-resolvers/runtime-functions.mdx`)

---
id: runtime-functions
title: "Runtime Functions"
slug: /api-reference/relay-resolvers/runtime-functions/
description: Runtime functions associated with Relay Resolvers
---

This page documents the runtime functions associated with Relay Resolvers. For an overview of Relay Resolvers and how to think about them, see the [Relay Resolvers](../../guides/relay-resolvers/introduction.mdx) guide.

## RelayModernStore


RelayModernStore exposes `batchLiveStateUpdates()`. See [Live Fields](../../guides/relay-resolvers/live-fields.mdx#batching) for more details of how to use this method.

## `readFragment()`

Derived resolver fields model data that is derived from other data in the graph. To read the data that a derived field depends on, they must use the `readFragment()` function which is exported from `relay-runtime`. This function accepts a GraphQL fragment and a fragment key, and returns the data for the fragment.

:::warning
`readFragment()` may only be used in Relay Resolvers. It will throw an error if used in any other context.
:::

```tsx
import {readFragment} from "relay-runtime";

/**
 * @relayField User.fullName: String
 * @rootFragment UserFullNameFragment
 */
export function fullName(key: UserFullNameFragment$key): string {
  const user = readFragment(graphql`
    fragment UserFullNameFragment on User {
      firstName
      lastName
    }
  `, key);
  return `${user.firstName} ${user.lastName}`;
}
```

Note that Relay will ensure your field resolver is recomputed any time data in that fragment changes.

See the [Derived Fields](../../guides/relay-resolvers/derived-fields.mdx) guide for more information.

## `suspenseSentinel()`

Live resolvers model client state that can change over time. If at some point during that field's lifecycle, the data being read is in a pending state, for example if the data is being fetched from an API, the resolver may return the `suspenseSentinel()` to indicate that the data is not yet available.

Relay expects that when the data is available, the `LiveStateValue` will notify Relay by calling the subscribe callback.

```tsx
import {suspenseSentinel} from 'relay-runtime';

/**
 * @relayField Query.myIp: String
 * @live
 */
export function myIp(): LiveState<string> {
  return {
    read: () => {
      const state = store.getState();
      const ipLoadObject = state.ip;
      if (ipLoadObject.status === "LOADING") {
        return suspenseSentinel();
      }
      return state.ip;
    },
    subscribe: (callback) => {
      return store.subscribe(callback);
    },
  };
}
```

See the [Live Fields](../../guides/relay-resolvers/live-fields.mdx) guide for more information.

## `useClientQuery()`

If a query contains only client fields, it may not currently be used with hooks like `usePreloadedQuery` and `useLazyLoadQuery` since both of those hooks assume they will need to issue a network request. If you attempt to use these APIs in Flow you will get a type error.

Instead, for client-only queries, you can use the `useClientQuery` hook:

```tsx
import {useClientQuery} from 'react-relay';

export function MyComponent() {
  const data = useClientQuery(graphql`
    query MyQuery {
      myIp
    }
  `);
  return <div>{data.myIp}</div>;
}
```

---

### Api Reference Relay Runtime Commit Mutation (`website/docs/api-reference/relay-runtime/commit-mutation.mdx`)

---
id: commit-mutation
title: commitMutation
slug: /api-reference/commit-mutation/
description: API reference for commitMutation, which imperatively executes a mutation
keywords:
  - mutation
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
import MutationConfig from '../types/MutationConfig.mdx';
import Disposable from '../types/Disposable.mdx';

## `commitMutation`

Imperatively execute a mutation.

See also the [`useMutation`](../use-mutation/) API and [Guide to Updating Data](../../guided-tour/updating-data/introduction.mdx).

```js
import type {FeedbackLikeMutation} from 'FeedbackLikeMutation.graphql';
const React = require('React');

const {graphql, commitMutation} = require('react-relay');

function likeFeedback(environment: IEnvironment): Disposable {
  return commitMutation<FeedbackLikeMutation>(environment, {
    mutation: graphql`
      mutation FeedbackLikeMutation($input: FeedbackLikeData!) {
        feedback_like(data: $input) {
          feedback {
            id
            viewer_does_like
            like_count
          }
        }
      }
    `,
    variables: {
      input: {
        id: '123',
      },
    },
  });
}
```

### Arguments

* `environment`: `IEnvironment`. A Relay environment.
* `config`: [`MutationConfig<TMutation>`](#type-mutationconfigtmutationconfig-mutationparameters).

<MutationConfig />


### Return Value

* A [`Disposable`](#interface-disposable) which:
  * If called before the request completes, will cancel and revert any optimistic updates and prevent the `onComplete` and `onError` callbacks from being executed. It will not necessarily cancel any network request. Will cause the `onUnsubscribe` callback to be called.
  * If called after the initial request completes, will do nothing.

<Disposable />

<DocsRating />

---

### Api Reference Relay Runtime Fetch Query (`website/docs/api-reference/relay-runtime/fetch-query.mdx`)

---
id: fetch-query
title: fetchQuery
slug: /api-reference/fetch-query/
description: API reference for fetchQuery, which imperatively fetches data for a query and returns an observable
keywords:
  - observable
  - query
  - fetch
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

## `fetchQuery`

If you want to fetch a query outside of React, you can use the `fetchQuery` function from `react-relay`:

```js
// You should prefer passing an environment that was returned from useRelayEnvironment()
const MyEnvironment = require('MyEnvironment');
const {fetchQuery} = require('react-relay');

fetchQuery(
  environment,
  graphql`
    query AppQuery($id: ID!) {
      user(id: $id) {
        name
      }
    }
  `,
  {id: 4},
)
.subscribe({
  start: () => {...},
  complete: () => {...},
  error: (error) => {...},
  next: (data) => {...}
});
```

### Arguments

* `environment`: A Relay Environment instance to execute the request on. If you're starting this request somewhere within a React component, you probably want to use the environment you obtain from using [`useRelayEnvironment`](../use-relay-environment/).
* `query`: GraphQL query to fetch, specified using a `graphql` template literal.
* `variables`: Object containing the variable values to fetch the query. These variables need to match GraphQL variables declared inside the query.
* `options`: *_[Optional]_* options object
    * `networkCacheConfig`: *_[Optional]_ *Object containing cache config options
        * `force`: Boolean value. If true, will bypass the network response cache. Defaults to true.
    * `fetchPolicy`: *_[Optional]_* Determines whether `fetchQuery` should reuse data that is already available in the local Relay store. Must be one of the following values:
        * `"network-only"`: *(default)* Always issue a network request, regardless of what is in the store.
        * `"store-or-network"`: Reuse data from the store if the full query is available locally; otherwise, issue a network request.

        The `"store-and-network"` and `"store-only"` fetch policies are **not supported** by `fetchQuery`, because it is designed around issuing a single network request and returning the response.

### Flow Type Parameters

* `TQuery`: Type parameter that should correspond to the Flow type for the specified query. This type is available to import from the the auto-generated file: `<query_name>.graphql.js`. It will ensure that the type of the data provided by the observable matches the shape of the query, and enforces that the `variables` passed as input to `fetchQuery` match the type of the variables expected by the query.

### Return Value

* `observable`: Returns an observable instance. To start the request, `subscribe` or `toPromise` must be called on the observable. Exposes the following methods:
    * `subscribe`: Function that can be called to subscribe to the observable for the network request. Keep in mind that this subscribes you only to the fetching of the query, not to any subsequent changes to the data within the Relay Store.
        * Arguments:
            * `observer`: Object that specifies observer functions for different events occurring on the network request observable. May specify the following event handlers as keys in the observer object:
                * `start`: Function that will be called when the network requests starts. It will receive a single `subscription` argument, which represents the subscription on the network observable.
                * `complete`: Function that will be called if and when the network request completes successfully.
                * `next`: Function that will be called every time a payload is received from the network. It will receive a single `data` argument, which represents a snapshot of the query data read from the Relay store at the moment a payload was received from the server.
                * `error`:  Function that will be called if an error occurs during the network request. It will receive a single `error` argument, containing the error that occurred.
                * `unsubscribe`: Function that will be called whenever the subscription is unsubscribed. It will receive a single `subscription` argument, which represents the subscription on the network observable.
        * Return Value:
            * `subscription`: Object representing a subscription to the observable. Calling `subscription.unsubscribe()` will cancel the network request.
    * `toPromise`:
        * Return Value:
            * `promise`: Returns a promise that will resolve when the first network response is received from the server. If the request fails, the promise will reject. Cannot be cancelled.

<FbInternalOnly>

:::info
The `next` function may be called multiple times when using Relay's [Incremental Data Delivery](../../guides/incremental-data-delivery/) capabilities to receive multiple payloads from the server.
:::

</FbInternalOnly>

### Behavior

* `fetchQuery` will automatically save the fetched data to the in-memory Relay store, and notify any components subscribed to the relevant data.
* `fetchQuery` will **NOT** retain the data for the query, meaning that it is not guaranteed that the data will remain saved in the Relay store at any point after the request completes. If you wish to make sure that the data is retained outside of the scope of the request, you need to call `environment.retain()` directly on the query to ensure it doesn't get deleted. See our section on [Controlling Relay's GC Policy](../../guided-tour/reusing-cached-data/presence-of-data) for more details.
* `fetchQuery` will automatically de-dupe identical network requests (same query and variables) that are in flight at the same time, and that were initiated with `fetchQuery`.


### Behavior with `.toPromise()`

If desired, you can convert the request into a Promise using `**.toPromise()**`. Note that toPromise will start the query and return a Promise that will resolve when the *first* piece of data returns from the server and *cancel further processing*. That means any deferred or 3D data in the query may not be processed. **We generally recommend against using toPromise() for this reason.**

```js
const {fetchQuery} = require('react-relay');

fetchQuery(
  environment,
  graphql`
    query AppQuery($id: ID!) {
      user(id: $id) {
        name
      }
    }
  `,
  {id: 4},
)
.toPromise() // NOTE: don't use, this can cause data to be missing!
.then(data => {...})
.catch(error => {...};
```

* `toPromise` Returns a promise that will resolve when the first network response is received from the server. If the request fails, the promise will reject. Cannot be cancelled.

<DocsRating />

---

### Api Reference Relay Runtime Field Logger (`website/docs/api-reference/relay-runtime/field-logger.mdx`)

---
id: field-logger
title: relayFieldLogger
slug: /api-reference/field-logger/
description: API reference for the `relayFieldLogger` Environment config option
keywords:
  - environment
  - logging
  - error
---

Relay includes a number of features that allow for granular handling of field errors:

- [`@required`](../../guides/required-directive.mdx) provides declarative handling of field nullability
- [`@catch`](../../guides/catch-directive.mdx) allows you to explicitly handle field errors
- [`@throwOnFieldError`](../../guides/throw-on-field-error-directive.mdx) lets you treat field errors as exceptions
- [Relay Resolvers](../../guides/relay-resolvers/introduction.mdx) coerce thrown exceptions to null, matching the GraphQL spec

In each of these cases, field errors are handled by Relay. However, it can still be important to track that these errors are occurring in your app, and monitor or resolve them. To enable this, the Relay Environment can be configured with a `relayFieldLogger`. This logger is a function which is called with events each time Relay handles a field-level error.

Providing a field logger looks something like this:
```ts
import {Environment} from "relay-runtime";

const environment = new Environment({
    relayFieldLogger: (event) => {
        switch(event.kind) {
            case "missing_expected_data.log":
                // ...
                break;
            // ... handle other events
        }
    },
    network: // ...
    store: // ...
});
```

## Event Types

The Field Logger currently can receive the following events:

## Missing Expected Data Log

Data which Relay expected to be in the store (because it was requested by the parent query/mutation/subscription) was missing. This can happen due to graph relationship changes observed by other queries/mutations, or imperative updates that don't provide all needed data.

See [Graph Relationship Changes](../../debugging/why-null/#graph-relationship-change).

In this case Relay will render with the referenced field as `undefined`.

:::note
This may break with the type contract of Relay's generated types.
:::

To turn this into a hard error for a given fragment/query, you can use [`@throwOnFieldError`](../../guides/throw-on-field-error-directive/)

```ts
export type MissingExpectedDataLogEvent = {
  +kind: 'missing_expected_data.log',
  +owner: string,
  +fieldPath: string,
};
```

## Missing Expected Data Throw

Data which Relay expected to be in the store (because it was requested by the parent query/mutation/subscription) was missing. This can happen due to graph relationship changes observed by other queries/mutations, or imperative updates that don't provide all needed data.

See [Graph Relationship Changes](../../debugging/why-null/#graph-relationship-change).


This event is called `.throw` because the missing data was encountered in a
 query/fragment/mutation with [`@throwOnFieldError`](../../guides/throw-on-field-error-directive/)

Relay will throw immediately after logging this event. If you wish to
customize the error being thrown, you may throw your own error.

:::note
Only throw on this event if `handled` is false. Errors that have been handled by a `@catch` directive or by making a resolver null will have `handled: true` and should not trigger a throw.
:::

```ts
export type MissingExpectedDataThrowEvent = {
  +kind: 'missing_expected_data.throw',
  +owner: string,
  +fieldPath: string,
  +handled: boolean,
};
```

The `fieldPath` property is a `.` separated string containing the path from the query/mutation/fragment root to the field which was missing. Note that there are some cases where we are missing data that is not strictly a field. In those cases the path will end with one of these segments:

1. `path.to.<record>` An edge points to an ID that is not present in the Relay store
2. `path.to.<abstract-type-hint>` A virtual field inserted by the Relay compiler to detect if a type condition holds is missing from the Relay store

## Missing Required Field Log

A field was marked as [@required(action: LOG)](../../guides/required-directive.mdx#action) but was null or missing in the store.

```ts
export type MissingRequiredFieldLogEvent = {
  +kind: 'missing_required_field.log',
  +owner: string,
  +fieldPath: string,
};
```

## Missing Required Field Throw

A field was marked as [@required(action: THROW)](../../guides/required-directive.mdx#action) but was null or missing in the store.

Relay will throw immediately after logging this event. If you wish to customize the error being thrown, you may throw your own error.

:::note
Only throw on this event if `handled` is false. Errors that have been
handled by a `@catch` directive or by making a resolver null will have
`handled: true` and should not trigger a throw.
:::

```ts
export type MissingRequiredFieldThrowEvent = {
  +kind: 'missing_required_field.throw',
  +owner: string,
  +fieldPath: string,
  +handled: boolean,
};
```

## Relay Resolver Error


A [Relay Resolver](../../guides/relay-resolvers/introduction.mdx) that is currently being read threw a JavaScript error when it was last evaluated. By default, the value has been coerced to null and passed to the product code.

If [`@throwOnFieldError`](../../guides/throw-on-field-error-directive.mdx) was used on the parent query/fragment/mutation, you will also receive a runtime exception when the field is read.

:::note
Only throw on this event if `handled` is false. Errors that have been handled by a `@catch` directive or by making a resolver null will have `handled: true` and should not trigger a throw.

```ts
export type RelayResolverErrorEvent = {
  +kind: 'relay_resolver.error',
  +owner: string,
  +fieldPath: string,
  +error: Error,
  +shouldThrow: boolean,
  +handled: boolean,
};
```

## GraphQL Payload Field Error


A field being read by Relay was marked as being in an error state by the [GraphQL response](https://spec.graphql.org/October2021/#sec-Errors.Field-errors)

If the field's parent query/fragment/mutation was annotated with [`@throwOnFieldError`](../../guides/throw-on-field-error-directive.mdx) and no [`@catch`](../../guides/catch-directive.mdx) directive was used to catch the error, Relay will throw an error immediately after logging this event.

:::note
Only throw on this event if `handled` is false. Errors that have been handled by a `@catch` directive or by making a resolver null will have `handled: true` and should not trigger a throw.
:::

```ts
export type RelayFieldPayloadErrorEvent = {
  +kind: 'relay_field_payload.error',
  +owner: string,
  +fieldPath: string,
  +error: TRelayFieldError,
  +shouldThrow: boolean,
  +handled: boolean,
};
```

---

### Api Reference Relay Runtime Observe Fragment (`website/docs/api-reference/relay-runtime/observe-fragment.mdx`)

---
id: observe-fragment
title: observeFragment
slug: api-reference/observe-fragment
description: Read the value of a fragment and observe its state and value over time
keywords:
  - observable
  - fragment
---

import DocsRating from '@site/src/core/DocsRating';

:::warning
`observeFragment` is still an experimental API. It currently has some limitations and may evolve slightly during this phase.
:::

## `observeFragment`

In some cases it can be useful to define data that you wish to read using a GraphQL fragment, but then consume it outside of React render function. `observeFragment` allows you to consume the state and value of a fragment as it changes over time. This includes loading and error states as well as changes to the data as it gets updated by local updates, mutations or updates to Relay's normalized store from other queries.

To read a fragment's data just once, see [`waitForFragmentData`](./wait-for-fragment-data.mdx).

:::caution
When using `observeFragment` with a plural fragment, the current implementation notifies the subscription multiple times if a store update impacting multiple list items gets published. Since the notifications happen synchronously, it is advised to debounce for a tick and only use the last payload for batching.
:::

### Example

```ts
import {observeFragment} from "relay-runtime/experimental";
import { useEffect } from "react";
import { useFragment } from "react-relay";
import { graphql } from "relay-runtime";

function MyComponent({ key }) {
  const user = useFragment(
    graphql`
      fragment UserFragment on User {
        ...TitleFragment
      }
    `,
    key,
  );

  // Update the title as the user's name changes without triggering rerenders.
  useEffect(() => {
    const subscription = observeFragment(
      graphql`
        fragment TitleFragment on User {
          name
        }
      `,
      user,
    ).subscribe({
      next: (result) => {
        switch(result.kind) {
          case "loading":
            window.title = "...loading";
            break;
          case "error":
            window.title = "Oops, we hit an error";
            break;
          case "ok":
            window.title = `Welcome ${result.value.name}`;
            break;
        }
      }
    });
    return () => {
      subscription.unsubscribe();
    };
  }, [user]);

  return <div>Check out the document title!</div>;
}
```

### Arguments

* `environment`: `IEnvironment`. A Relay environment.
* `fragment`: GraphQL fragment specified using a `graphql` template literal.
* `fragmentReference`: The *fragment reference* is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from.
    * The type of the fragment reference can be imported from the generated Flow types, from the file `<fragment_name>.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `<fragment_name>$key`. We use our [lint rule](https://github.com/relayjs/eslint-plugin-relay) to enforce that the type of the fragment reference prop is correctly declared.

### Return Value

* An [`Observable`](../../glossary/glossary.mdx#observable) which returns a discriminated union modeling the three possible states in which a fragment's data might be:
  * `{state: 'ok', value: T}` - When data is available the state is `'ok'`. `T` is the data defined in the fragment.
  * `{state: 'error': error: Error}` - When the fragment is in an error state either due to network level errors, [`@throwOnFieldError`](../../guides/throw-on-field-error-directive.mdx) or [`@required(action: THROW)`](../../guides/required-directive.mdx) field errors.
  * `{state: 'loading'}` - When the parent request, or current `@defer` payload is still in flight, or a [`@live` Relay Resolver](../../guides/relay-resolvers/live-fields.mdx) being read is in a suspended state.

<DocsRating />

---

### Api Reference Relay Runtime Relay Environment (`website/docs/api-reference/relay-runtime/relay-environment.mdx`)

---
id: relay-environment
title: Relay Environment
slug: /api-reference/relay-runtime/relay-environment
description: Setting up a Relay Environment
---

The core of Relay's runtime is the `Environment`. The environment knows how to make requests to your GraphQL server and contains the `Store`, Relay's normalized data cache. Generally your application will construct a single environment which is configured to fetch data from your server, and then expose that environment to all of your components via `RelayEnvironmentProvider`.

## Creating an Environment

To create your environment you must provide two key pieces, a [`Network`](../../guides/network-layer.mdx) and a [`Store`](store.mdx).

The `Network` is responsible for making requests to your GraphQL server. The `Store` holds the normalized data cache.

A minimal implementation of an environment might look like this:

```ts title="RelayEnvironment.js"
import { Environment, Store, RecordSource, 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();
};

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

## Advanced Configuration

The Relay environment accepts a number of additional configuration options when it is created. These options are all optional, but can be used to customize the behavior of the environment.

Notable options include:

* `log` - A function that will be called with telemetry events. See the types for [`LogEvent`](https://github.com/facebook/relay/blob/0414c9ad0744483e349e07defcb6d70a52cf8b3c/packages/relay-runtime/store/RelayStoreTypes.js#L799) for a full list of events and their fields.
* [`missingFieldHandlers`](../../guided-tour/reusing-cached-data/filling-in-missing-data.mdx) - A list of handlers that will be called when a field is missing from the store. This can be used to enable fulfilling queries to fields like `Query.node` from cache.
* `getDataID` - A function that will be called to generate a unique ID for a given object. This can be used to customize the way that Relay generates IDs for objects if your server does not implement the [Global Object Identification spec](https://graphql.org/learn/global-object-identification/).
* [`relayFieldLogger`](./field-logger.mdx) - A function that will be called when Relay encounters a field-level error.
* `deferDeduplicatedFields` - When set to `true`, this option prevents Relay from throwing an error when missing fields are received in a deferred response. This is required for the [latest](https://github.com/graphql/defer-stream-wg/discussions/69) `@defer` spec proposal, which does not send duplicate fields in deferred responses. While Relay does not yet attempt to support the latest spec proposal, this option allows users to transform responses into a format that Relay can accept.

For a full list of options, inspect the [provided TypeScript types](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/relay-runtime/lib/store/RelayModernEnvironment.d.ts#L26-L43).

---

### Api Reference Relay Runtime Request Subscription (`website/docs/api-reference/relay-runtime/request-subscription.mdx`)

---
id: request-subscription
title: requestSubscription
slug: /api-reference/request-subscription/
description: API reference for requestSubscription, which imperatively establishes a GraphQL subscription
keywords:
  - subscription
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
import GraphQLSubscriptionConfig from '../types/GraphQLSubscriptionConfig.mdx';
import Disposable from '../types/Disposable.mdx';

## `requestSubscription`

Imperative API for establishing a GraphQL Subscription.
See also the [`useSubscription`](../use-subscription/) API and the [Guide to Updating Data](../../guided-tour/updating-data/introduction.mdx).
```js
import {graphql, requestSubscription} from 'react-relay';

const subscription = graphql`
  subscription UserDataSubscription($input: InputData!) {
    # ...
  }
`;

function createSubscription(environment: IEnvironment): Disposable {
  return requestSubscription(environment, {
    subscription,
    variables: {input: {userId: '4'}},
  });
}
```

### Arguments

* `environment`: A Relay Environment
* `config`: `GraphQLSubscriptionConfig`

<GraphQLSubscriptionConfig />

### Return Type

* A [`Disposable`](#interface-disposable) that clears the subscription.

<Disposable />

### Behavior

* Imperatively establish a subscription.
* See the [GraphQL Subscriptions Guide](../../guided-tour/updating-data/graphql-subscriptions/) for a more detailed explanation of how to work with subscriptions.

<DocsRating />

---

### Api Reference Relay Runtime Runtime Configuration (`website/docs/api-reference/relay-runtime/runtime-configuration.mdx`)

---
id: runtime-config
title: Runtime Configuration
slug: /api-reference/runtime-config/
description: Configuring the Relay Runtime
keywords:
  - feature flags
  - configuration
---

## ConnectionInterface

If your server's implementation of the Connection Spec differs from the default interface you will need to configure the Relay Runtime to expect the connection type and field names used in your schema. This is done by updating the global ConnectionInterface instance exported by Relay:

:::note
You will also need to update your [Relay Compiler Config](../../getting-started/compiler-config/#ConnectionInterface) with these same values at the path `schemaConfig.connectionInterface`.
:::

```ts title="/src/ConfigureRelay.ts"
import { ConnectionInterface } from 'relay-runtime';

// Note: This must match the values configured in the Relay compiler config.
ConnectionInterface.inject({
  END_CURSOR: 'end_cursor',
  HAS_NEXT_PAGE: 'has_next_page',
  HAS_PREV_PAGE: 'has_previous_page',
  START_CURSOR: 'start_cursor',
  PAGE_INFO: 'page_info',
  NODE: 'node',
  CURSOR: 'cursor',
  EDGES: 'edges',
  PAGE_INFO_TYPE: 'PageInfo',
});
```

## Feature Flags

:::warning
Feature Flags are used for enabling and configuring unstable Relay features, **regular use of Relay should not need to modify runtime feature flags**. They are documented here for purely informational purposes
:::

Relay has a number of runtime options called "Feature Flags". In general, these are used for enabling experimental features which are not yet stable and thus not yet enabled by default.

Feature flags in the Relay Runtime are implemented as a global mutable object. To set/configure a feature flag, import that object and mutate it. If you do this in the module scope, the updates will apply before Relay looks at them.

```ts title="/src/ConfigureRelay.ts"
import { RelayFeatureFlags } from 'relay-runtime';

RelayFeatureFlags.ENABLE_SOME_EXPERIMENT = true;
```

You can find the full list of feature flags [here](https://github.com/facebook/relay/blob/203d8b10e9144a37466b8a72edbe6add48f64e7d/packages/relay-runtime/util/RelayFeatureFlags.js#L4), but keep in mind that **feature flags may change arbitrarily between versions of Relay**.

---

### Api Reference Relay Runtime Store (`website/docs/api-reference/relay-runtime/store.mdx`)

---
id: store
title: Store
slug: /api-reference/store/
description: API reference for the Relay store
keywords:
  - store
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

The Relay Store can be used to programmatically update client-side data inside [`updater` functions](../../guided-tour/updating-data/graphql-mutations/). The following is a reference of the Relay Store interface.

Table of Contents:

-   [RecordSourceSelectorProxy](#recordsourceselectorproxy)
-   [RecordProxy](#recordproxy)
-   [RecordSourceProxy](#recordsourceproxy)
-   [ConnectionHandler](#connectionhandler)

## RecordSourceSelectorProxy

The `RecordSourceSelectorProxy` is the type of the `store` that [`updater` functions](../../guided-tour/updating-data/graphql-mutations/) receive as an argument. The following is the `RecordSourceSelectorProxy` interface:

```javascript
interface RecordSourceSelectorProxy {
  create(dataID: string, typeName: string): RecordProxy;
  delete(dataID: string): void;
  get(dataID: string): ?RecordProxy;
  getRoot(): RecordProxy;
  getRootField(fieldName: string): ?RecordProxy;
  getPluralRootField(fieldName: string): ?Array<?RecordProxy>;
  invalidateStore(): void;
}
```

### `create(dataID: string, typeName: string): RecordProxy`

Creates a new record in the store given a `dataID` and the `typeName` as defined by the GraphQL schema. Returns a [`RecordProxy`](#recordproxy) which serves as an interface to mutate the newly created record.

#### Example

```javascript
const record = store.create(dataID, 'Todo');
```

### `delete(dataID: string): void`

Deletes a record from the store given its `dataID`. For existing edges to the deleted record, `undefined` will be returned in the default case even when the value is typed as non-nullable. When [`@throwOnFieldError`](../../guides/throw-on-field-error-directive/) is present, the missing data will throw an error.

#### Example

```javascript
store.delete(dataID);
```

### `get(dataID: string): ?RecordProxy`

Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`](#recordproxy) which serves as an interface to mutate the record.

#### Example

```javascript
const record = store.get(dataID);
```

### `getRoot(): RecordProxy`

Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL document.

#### Example

Given the GraphQL document:

```graphql
viewer {
  id
}
```

Usage:

```javascript
// Represents root query
const root = store.getRoot();
// Get the viewer linked record
const viewer = root.getLinkedRecord('viewer');
```

### `getRootField(fieldName: string): ?RecordProxy`

Retrieves a root field from the store given the `fieldName`, as defined by the GraphQL document. Returns a [`RecordProxy`](#recordproxy) which serves as an interface to mutate the record.

#### Example

Given the GraphQL document:

```graphql
viewer {
  id
}
```

Usage:

```javascript
const viewer = store.getRootField('viewer');
```

### `getPluralRootField(fieldName: string): ?Array<?RecordProxy>`

Retrieves a root field that represents a collection from the store given the `fieldName`, as defined by the GraphQL document. Returns an array of [`RecordProxies`](#recordproxy).

#### Example

Given the GraphQL document:

```graphql
nodes(first: 10) {
  # ...
}
```

Usage:

```javascript
const nodes = store.getPluralRootField('nodes');
```

### `invalidateStore(): void`

Globally invalidates the Relay store. This will cause any data that was written to the store before invalidation occurred to be considered stale, and will be considered to require refetch the next time a query is checked with `environment.check()`.

#### Example

```javascript
store.invalidateStore();
```

After global invalidation, any query that is checked before refetching it will be considered stale:

```javascript
environment.check(query) === 'stale'
```

## RecordProxy

The `RecordProxy` serves as an interface to mutate records:

```javascript
interface RecordProxy {
  copyFieldsFrom(sourceRecord: RecordProxy): void;
  getDataID(): string;
  getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy;
  getLinkedRecords(name: string, arguments?: ?Object): ?Array<?RecordProxy>;
  getOrCreateLinkedRecord(
    name: string,
    typeName: string,
    arguments?: ?Object,
  ): RecordProxy;
  getType(): string;
  getValue(name: string, arguments?: ?Object): mixed;
  setLinkedRecord(
    record: RecordProxy,
    name: string,
    arguments?: ?Object,
  ): RecordProxy;
  setLinkedRecords(
    records: Array<?RecordProxy>,
    name: string,
    arguments?: ?Object,
  ): RecordProxy;
  setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy;
  invalidateRecord(): void;
}
```

### `getDataID(): string`

Returns the `dataID` of the current record.

#### Example

```javascript
const id = record.getDataID();
```

### `getType(): string`

Gets the type of the current record, as defined by the GraphQL schema.

#### Example

```javascript
const type = user.getType();  // User
```

### `getValue(name: string, arguments?: ?Object): mixed`

Gets the value of a field in the current record given the field name.

#### Example

Given the GraphQL document:

```graphql
viewer {
  id
  name
}
```

Usage:

```javascript
const name = viewer.getValue('name');
```

Optionally, if the field takes arguments, you can pass a bag of `variables`.

#### Example

Given the GraphQL document:

```graphql
viewer {
  id
  name(arg: $arg)
}
```

Usage:

```javascript
const name = viewer.getValue('name', {arg: 'value'});
```

### `getLinkedRecord(name: string, arguments?: ?Object): ?RecordProxy`

Retrieves a record associated with the current record given the field name, as defined by the GraphQL document. Returns a `RecordProxy`.

#### Example

Given the GraphQL document:

```graphql
rootField {
  viewer {
    id
    name
  }
}
```

Usage:

```javascript
const rootField = store.getRootField('rootField');
const viewer = rootField.getLinkedRecord('viewer');
```

Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well.

#### Example

Given the GraphQL document:

```graphql
rootField {
  viewer(arg: $arg) {
    id
  }
}
```

Usage:

```javascript
const rootField = store.getRootField('rootField');
const viewer = rootField.getLinkedRecord('viewer', {arg: 'value'});
```

### `getLinkedRecords(name: string, arguments?: ?Object): ?Array<?RecordProxy>`

Retrieves the set of records associated with the current record given the field name, as defined by the GraphQL document. Returns an array of `RecordProxies`.

#### Example

Given the GraphQL document:

```graphql
rootField {
  nodes {
    # ...
  }
}
```

Usage:

```javascript
const rootField = store.getRootField('rootField');
const nodes = rootField.getLinkedRecords('nodes');
```

Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well.

#### Example

Given the GraphQL document:

```graphql
rootField {
  nodes(first: $count) {
    # ...
  }
}
```

Usage:

```javascript
const rootField = store.getRootField('rootField');
const nodes = rootField.getLinkedRecords('nodes', {count: 10});
```

### `getOrCreateLinkedRecord(name: string, typeName: string, arguments?: ?Object)`

Retrieves a record associated with the current record given the field name, as defined by the GraphQL document. If the linked record does not exist, it will be created given the type name. Returns a `RecordProxy`.

#### Example

Given the GraphQL document:

```graphql
rootField {
  viewer {
    id
  }
}
```

Usage:

```javascript
const rootField = store.getRootField('rootField');
const newViewer = rootField.getOrCreateLinkedRecord('viewer', 'User'); // Will create if it doesn't exist
```

Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well.

### `setValue(value: mixed, name: string, arguments?: ?Object): RecordProxy`

Mutates the current record by setting a new value on the specified field. Returns the mutated record.

Given the GraphQL document:

```graphql
viewer {
  id
  name
}
```

Usage:

```javascript
viewer.setValue('New Name', 'name');
```

Optionally, if the field takes arguments, you can pass a bag of `variables`.

```javascript
viewer.setValue('New Name', 'name', {arg: 'value'});
```

### `copyFieldsFrom(sourceRecord: RecordProxy): void`

Mutates the current record by copying the fields over from the passed in record `sourceRecord`.

#### Example

```javascript
const record = store.get(id1);
const otherRecord = store.get(id2);
record.copyFieldsFrom(otherRecord); // Mutates `record`
```

### `setLinkedRecord(record: RecordProxy, name: string, arguments?: ?Object)`

Mutates the current record by setting a new linked record on the given field name.

#### Example

Given the GraphQL document:

```graphql
rootField {
  viewer {
    id
  }
}
```

Usage:

```javascript
const rootField = store.getRootField('rootField');
const newViewer = store.create(/* ... */);
rootField.setLinkedRecord(newViewer, 'viewer');
```

Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well.

### `setLinkedRecords(records: Array<RecordProxy>, name: string, variables?: ?Object)`

Mutates the current record by setting a new set of linked records on the given field name.

#### Example

Given the GraphQL document:

```graphql
rootField {
  nodes {
    # ...
  }
}
```

Usage:

```javascript
const rootField = store.getRootField('rootField');
const newNode = store.create(/* ... */);
const newNodes = [...rootField.getLinkedRecords('nodes'), newNode];
rootField.setLinkedRecords(newNodes, 'nodes');
```

Optionally, if the linked record takes arguments, you can pass a bag of `variables` as well.

### `invalidateRecord(): void`

Invalidates the record. This will cause any query that references this record to be considered stale until the next time it is refetched, and will be considered to require a refetch the next time such a query is checked with `environment.check()`.

#### Example

```javascript
const record = store.get('4');
record.invalidateRecord();
```

After invalidating a record, any query that references the invalidated record and that is checked before refetching it will be considered stale:

```javascript
environment.check(query) === 'stale'
```

## RecordSourceProxy

The `RecordSourceProxy` serves as an interface to mutate records.

:::danger
`RecordSourceProxy` exposes many low level APIs that are not typesafe. Users should consider using [typesafe updaters](../../guided-tour/updating-data/typesafe-updaters-faq/), [optimistic updates](../../guided-tour/updating-data/graphql-mutations/#optimistic-updates), and [relay resolvers](../../guides/relay-resolvers/introduction/) instead if their use case can be covered by these alternatives.
:::

```javascript
interface RecordSourceProxy {
  create(dataID: DataID, typeName: string): RecordProxy;
  delete(dataID: DataID): void;
  get(dataID: DataID): ?RecordProxy;
  getRoot(): RecordProxy;
  invalidateStore(): void;
  readUpdatableFragment<TFragmentType: FragmentType, TData>(
    fragment: UpdatableFragment<TFragmentType, TData>,
    fragmentReference: HasUpdatableSpread<TFragmentType>,
  ): UpdatableData<TData>;
  readUpdatableQuery<TVariables: Variables, TData>(
    query: UpdatableQuery<TVariables, TData>,
    variables: TVariables,
  ): UpdatableData<TData>;
}
```

### `create(dataID: DataID, typeName: string): RecordProxy`

Creates a new record in the store given a `dataID` and the `typeName` as defined by the GraphQL schema. Returns a [`RecordProxy`](#recordproxy) which serves as an interface to mutate the newly created record.

#### Example

```javascript
const record = store.create(dataID, 'Todo');
```

### `delete(dataID: DataID): void`

Deletes a record from the store given its `dataID`. For existing edges to the deleted record, `undefined` will be returned in the default case even when the value is typed as non-nullable. When [`@throwOnFieldError`](../../guides/throw-on-field-error-directive/) is present, the missing data will throw an error.

#### Example

```javascript
store.delete(dataID);
```

### `get(dataID: DataID): ?RecordProxy`

Retrieves a record from the store given its `dataID`. Returns a [`RecordProxy`](#recordproxy) which serves as an interface to read/mutate the record.

#### Example

```javascript
const record = store.get(dataID);
```

### `getRoot(): RecordProxy`

Returns the [`RecordProxy`](#recordproxy) representing the root of the GraphQL document.

#### Example

Given the GraphQL document:

```graphql
viewer {
  id
}
```

Usage:

```javascript
// Represents root query
const root = store.getRoot();
// Get the viewer linked record
const viewer = root.getLinkedRecord('viewer');
```

### `invalidateStore(): void;`

Globally invalidates the Relay store. This will cause any data that was written to the store before invalidation occurred to be considered stale, and will be considered to require refetch the next time a query is checked with `environment.check()` or is fetched with a `store-or-network` [fetch policy](../../guided-tour/reusing-cached-data/fetch-policies/).

#### Example

```javascript
store.invalidateStore();
```

After global invalidation, any query that is checked before refetching it will be considered stale:

```javascript
environment.check(query) === 'stale'
```

### `readUpdatableFragment(fragment: UpdatableFragment<TFragmentType, TData>,fragmentReference: HasUpdatableSpread<TFragmentType>): UpdatableData<TData>;`

Fetches an updatable fragment from the store. This updatable fragment's fields can then be imperatively modified to update data in the store.

For more information on updating the store imperatively, see this [section](../../guided-tour/updating-data/imperatively-modifying-store-data/) of the guided tour.

#### Example
```javascript
const fragment = graphql`
  fragment StoryLikeButton_updatable on Story @updatable {
    likeCount
    doesViewerLike
  }
`;
const {
  updatableData
} = store.readUpdatableFragment(
  fragment,
  story
);
updatableData.likeCount = updatableData.likeCount + 1
```

### `readUpdatableQuery(query: UpdatableQuery<TVariables, TData>,variables: TVariables): UpdatableData<TData>`

Reads an updatable query from the store. This updatable query's fields can be imperatively modified to update data in the store. Unlike `readUpdatableFragment`, you do not need to pass in a `fragmentReference` as an input argument.

For more information on updating the store imperatively, see this [section](../../guided-tour/updating-data/imperatively-modifying-store-data/) of the guided tour.

#### Example

```javascript
const {updatableData} = store.readUpdatableQuery(
  graphql`
    query NameUpdaterUpdateQuery @updatable {
      viewer {
        name
      }
    }
  `,
  {}
);
const viewer = updatableData.viewer;
viewer.name = newName;
```

## ConnectionHandler

`ConnectionHandler` is a utility module exposed by `relay-runtime` that aids in the manipulation of connections. `ConnectionHandler` exposes the following interface:

```javascript
interface ConnectionHandler {
  getConnection(
    record: RecordProxy,
    key: string,
    filters?: ?Object,
  ): ?RecordProxy,
  createEdge(
    store: RecordSourceProxy,
    connection: RecordProxy,
    node: RecordProxy,
    edgeType: string,
  ): RecordProxy,
  insertEdgeBefore(
    connection: RecordProxy,
    newEdge: RecordProxy,
    cursor?: ?string,
  ): void,
  insertEdgeAfter(
    connection: RecordProxy,
    newEdge: RecordProxy,
    cursor?: ?string,
  ): void,
  deleteNode(connection: RecordProxy, nodeID: string): void
}
```

### `getConnection(record: RecordProxy, key: string, filters?: ?Object)`

Given a record and a connection key, and optionally a set of filters, `getConnection` retrieves a [`RecordProxy`](#recordproxy) that represents a connection that was annotated with a `@connection` directive.

First, let's take a look at a plain connection:

```graphql
fragment FriendsFragment on User {
  friends(first: 10) {
    edges {
      node {
        id
      }
    }
  }
}
```

Accessing a plain connection field like this is the same as other regular fields:

```javascript
// The `friends` connection record can be accessed with:
const user = store.get(userID);
const friends = user && user.getLinkedRecord('friends');

// Access fields on the connection:
const edges = friends && friends.getLinkedRecords('edges');
```

When using [usePaginationFragment](../use-pagination-fragment/), we usually annotate the actual connection field with `@connection` to tell Relay which part needs to be paginated:

```graphql
fragment FriendsFragment on User {
  friends(first: 10, orderby: "firstname") @connection(
    key: "FriendsFragment_friends",
  ) {
    edges {
      node {
        id
      }
    }
  }
}
```

For connections like the above, `ConnectionHandler` helps us find the record:

```javascript
import {ConnectionHandler} from 'relay-runtime';

// The `friends` connection record can be accessed with:
const user = store.get(userID);
const friends = ConnectionHandler.getConnection(
 user,                        // parent record
 'FriendsFragment_friends',   // connection key
 {orderby: 'firstname'}       // 'filters' that is used to identify the connection
);
// Access fields on the connection:
const edges = friends.getLinkedRecords('edges');
```

### Edge creation and insertion

#### `createEdge(store: RecordSourceProxy, connection: RecordProxy, node: RecordProxy, edgeType: string)`

Creates an edge given a [`store`](#recordsourceselectorproxy), a connection, the edge node, and the edge type.

#### `insertEdgeBefore(connection: RecordProxy, newEdge: RecordProxy, cursor?: ?string)`

Given a connection, inserts the edge at the beginning of the connection, or before the specified `cursor`.

#### `insertEdgeAfter(connection: RecordProxy, newEdge: RecordProxy, cursor?: ?string)`

Given a connection, inserts the edge at the end of the connection, or after the specified `cursor`.

#### Example

```javascript
const user = store.get(userID);
const friends = ConnectionHandler.getConnection(user, 'FriendsFragment_friends');
const newFriend = store.get(newFriendId);
const edge = ConnectionHandler.createEdge(store, friends, newFriend, 'UserEdge');

// No cursor provided, append the edge at the end.
ConnectionHandler.insertEdgeAfter(friends, edge);

// No cursor provided, insert the edge at the front:
ConnectionHandler.insertEdgeBefore(friends, edge);
```

### `deleteNode(connection: RecordProxy, nodeID: string): void`

Given a connection, deletes any edges whose node id matches the given id.

#### Example

```javascript
const user = store.get(userID);
const friends = ConnectionHandler.getConnection(user, 'FriendsFragment_friends');
ConnectionHandler.deleteNode(friends, idToDelete);
```

<DocsRating />

---

### Api Reference Relay Runtime Wait For Fragment Data (`website/docs/api-reference/relay-runtime/wait-for-fragment-data.mdx`)

---
id: wait-for-fragment-data
title: waitForFragmentData
slug: /api-reference/wait-for-fragment-data/
description: Read the value of a fragment as a promise
keywords:
  - promise
  - fragment
---

import DocsRating from '@site/src/core/DocsRating';

:::warning
`waitForFragmentData` is still an experimental API. It currently has some limitations and may evolve slightly during this phase.
:::

## `waitForFragmentData`

In some cases it can be useful to define data that you wish to read using a GraphQL fragment, but then consume it just once outside of React render function. `waitForFragmentData` allows you to wait for the data of a fragment to be available,

To read a fragment's data as it changes over time, see [`observeFragment`](./observe-fragment.mdx).

### Example: Deferring data used in an event handler

One use case for `waitForFragmentData` is to defer fetching data that is needed inside an event handler, but is not needed to render the initial view.

```tsx
import { useCallback } from "react";
import { useFragment } from "react-relay";
import { graphql } from "relay-runtime";
import { waitForFragmentData } from "relay-runtime/experimental";

function MyComponent({ key }) {
  const user = useFragment(
    graphql`
      fragment UserFragment on User {
        name
        # Page load can complete before this data has streamed in from the server.
        ...EventHandlerFragment @defer
      }
    `,
    key,
  );

  const onClick = useCallback(async () => {
    // Once the user clicks, we may need to wait for the data to finish loading.
    const userData = await waitForFragmentData(
      graphql`
        fragment EventHandlerFragment on User {
          age
        }
      `,
      user,
    );

    if (userData.age < 10) {
      alert("Hello kiddo!");
    } else if (userData.age < 18) {
      alert("Hello young person!");
    } else {
      alert("Hello adult person!");
    }
  }, [user]);

  return (
    <div>
      My name is {user.name}
      <button onClick={onClick}>Greet</button>
    </div>
  );
}
```

### Arguments

* `environment`: `IEnvironment`. A Relay environment.
* `fragment`: GraphQL fragment specified using a `graphql` template literal.
* `fragmentReference`: The *fragment reference* is an opaque Relay object that Relay uses to read the data for the fragment from the store; more specifically, it contains information about which particular object instance the data should be read from.
    * The type of the fragment reference can be imported from the generated Flow types, from the file `<fragment_name>.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `<fragment_name>$key`. We use our [lint rule](https://github.com/relayjs/eslint-plugin-relay) to enforce that the type of the fragment reference prop is correctly declared.

### Return Value

* A `Promise<T>` where `T` is the data defined in the fragment.

The Promise will wait for all network data to become available as well as any [`@live` Relay Resolver](../../guides/relay-resolvers/live-fields.mdx) to be in a non-suspended state before it resolves.

In the case of a network error, or a field-level error due to [`@throwOnFieldError`](../../guides/throw-on-field-error-directive.mdx) or [`@required(action: THROW)`](../../guides/required-directive.mdx), the Promise will reject with an error.

<DocsRating />

---

### Api Reference Types CacheConfig (`website/docs/api-reference/types/CacheConfig.mdx`)

#### Type `CacheConfig`

* An object with the following fields:
  * `force`: *_[Optional]_* A boolean. If true, causes a query to be issued unconditionally, regardless of the state of any configured response cache.
  * `poll`: *_[Optional]_* A number. Causes a query to live-update by polling at the specified interval, in milliseconds. (This value will be passed to `setTimeout`).
  * `liveConfigId`: *_[Optional]_* A string. Causes a query to live-update by calling GraphQLLiveQuery; it represents a configuration of gateway when doing live query.
  * `metadata`: *_[Optional]_* An object. User-supplied metadata.
  * `transactionId`: *_[Optional]_* A string. A user-supplied value, intended for use as a unique id for a given instance of executing an operation.

---

### Api Reference Types Disposable (`website/docs/api-reference/types/Disposable.mdx`)

#### Interface `Disposable`

* An object with the following key:
  * `dispose`: `() => void`. Disposes of the resource.

---

### Api Reference Types GraphQLSubscriptionConfig (`website/docs/api-reference/types/GraphQLSubscriptionConfig.mdx`)

import SelectorStoreUpdater from './SelectorStoreUpdater.mdx';
import CacheConfig from './CacheConfig.mdx';

#### Type `GraphQLSubscriptionConfig<TSubscriptionPayload>`

* An object with the following fields:
  * `cacheConfig`: *_[Optional]_* [`CacheConfig`](#type-cacheconfig)
  * `subscription`: `GraphQLTaggedNode`. A GraphQL subscription specified using a `graphql` template literal
  * `variables`: The variables to pass to the subscription
  * `onCompleted`: *_[Optional]_* `() => void`. An optional callback that is executed when the subscription is established
  * `onError`: *_[Optional]_* `(Error) => {}`. An optional callback that is executed when an error occurs
  * `onNext`: *_[Optional]_* `(TSubscriptionPayload) => {}`. An optional callback that is executed when new data is received
  * `updater`: *_[Optional]_* [`SelectorStoreUpdater`](#type-selectorstoreupdater).

<CacheConfig />

<SelectorStoreUpdater />

---

### Api Reference Types MutationConfig (`website/docs/api-reference/types/MutationConfig.mdx`)

import CacheConfig from './CacheConfig.mdx';
import SelectorStoreUpdater from './SelectorStoreUpdater.mdx';
import UploadableMap from './UploadableMap.mdx';

#### Type `MutationConfig<TMutationConfig: MutationParameters>`

* An object with the following fields:
  * `cacheConfig`: *_[Optional]_* [`CacheConfig`](#type-cacheconfig)
  * `mutation`: `GraphQLTaggedNode`. A mutation specified using a GraphQL literal
  * `onError`: *_[Optional]_* `(Error) => void`. An optional callback executed if the mutation results in an error.
  * `onCompleted`: *_[Optional]_* `($ElementType<TMutationConfig, 'response'>) => void`. An optional callback that is executed when the mutation completes.
    * The value passed to `onCompleted` is the mutation fragment, as read out from the store, **after** updaters and declarative mutation directives are applied. This means that data from within unmasked fragments will not be read, and records that were deleted (e.g. by `@deleteRecord`) may also be null.
  * `onUnsubscribe`: *_[Optional]_* `() => void`. An optional callback that is executed when the mutation is unsubscribed, which occurs when the returned `Disposable` is disposed.
  * `optimisticResponse`: *_[Optional]_* An object whose type matches the raw response type of the mutation. Make sure you decorate your mutation with `@raw_response_type` if you are using this field.
  * `optimisticUpdater`: *_[Optional]_* [`SelectorStoreUpdater`](#type-selectorstoreupdater). A callback that is executed when `commitMutation` is called, after the `optimisticResponse` has been normalized into the store.
  * `updater`: *_[Optional]_* [`SelectorStoreUpdater`](#type-selectorstoreupdater). A callback that is executed when a payload is received, after the payload has been written into the store.
  * `uploadables`: *_[Optional]_* [`UploadableMap`](#type-uploadablemap). An optional uploadable map.
  * `variables`: `$ElementType<TMutationConfig, 'variables'>`. The variables to pass to the mutation.

<CacheConfig />

<SelectorStoreUpdater />

<UploadableMap />

#### Type `MutationParameters`

* An object with the following fields:
  * `response`: An object
  * `variables`: An object
  * `rawResponse`: An optional object

---

### Api Reference Types SelectorStoreUpdater (`website/docs/api-reference/types/SelectorStoreUpdater.mdx`)

import useBaseUrl from '@docusaurus/useBaseUrl';

#### Type `SelectorStoreUpdater`

* A function with signature `(store: RecordSourceSelectorProxy, data) => void`
* This interface allows you to *imperatively* write and read data directly to and from the Relay store. This means that you have full control over how to update the store in response to the subscription payload: you can *create entirely new records*, or *update or delete existing ones*. The full API for reading and writing to the Relay store is available <a href={useBaseUrl('docs/api-reference/store/#recordsourceselectorproxy')}>here</a>.

---

### Api Reference Types UploadableMap (`website/docs/api-reference/types/UploadableMap.mdx`)

#### Type `UploadableMap`

* An object whose values are [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) or [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).

---

### Guided Tour List Data Advanced Pagination (`website/docs/guided-tour/list-data/advanced-pagination.mdx`)

---
id: advanced-pagination
title: Advanced Pagination
slug: /guided-tour/list-data/advanced-pagination/
description: Relay guide for advanced pagination
keywords:
- pagination
- usePaginationFragment
- prefetching
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

In this section we're going to cover how to implement more advanced pagination use cases than the default cases covered by `usePaginationFragment`.


## Pagination Over Multiple Connections

If you need to paginate over multiple connections within the same component, you can use `usePaginationFragment` multiple times:

```js
import type {CombinedFriendsListComponent_user$key} from 'CombinedFriendsListComponent_user.graphql';
import type {CombinedFriendsListComponent_viewer$key} from 'CombinedFriendsListComponent_viewer.graphql';

const React = require('React');

const {graphql, usePaginationFragment} = require('react-relay');

type Props = {
  user: CombinedFriendsListComponent_user$key,
  viewer: CombinedFriendsListComponent_viewer$key,
};

function CombinedFriendsListComponent(props: Props) {

  const {data: userData, ...userPagination} = usePaginationFragment(
    graphql`
      fragment CombinedFriendsListComponent_user on User {
        name
        friends
          @connection(
            key: "CombinedFriendsListComponent_user_friends_connection"
          ) {
          edges {
            node {
              name
              age
            }
          }
        }
      }
    `,
    props.user,
  );

  const {data: viewerData, ...viewerPagination} = usePaginationFragment(
    graphql`
      fragment CombinedFriendsListComponent_user on Viewer {
        actor {
          ... on User {
            name
            friends
              @connection(
                key: "CombinedFriendsListComponent_viewer_friends_connection"
              ) {
              edges {
                node {
                  name
                  age
                }
              }
            }
          }
        }
      }
    `,
    props.viewer,
  );

  return (...);
}
```

However, we recommend trying to keep a single connection per component, to keep the components easier to follow.



## Bi-directional Pagination

In the [Pagination](../pagination/) section we covered how to use `usePaginationFragment` to paginate in a single *"forward"* direction. However, connections also allow paginating in the opposite *"backward"* direction. The meaning of *"forward"* and *"backward"* directions will depend on how the items in the connection are sorted, for example  *"forward"* could mean more recent*, and "backward"* could mean less recent.

Regardless of the semantic meaning of the direction, Relay also provides the same APIs to paginate in the opposite direction, using `usePaginationFragment`, as long  as the `before` and `last` connection arguments are also used along with `after` and `first`:

```js
import type {FriendsListComponent_user$key} from 'FriendsListComponent_user.graphql';

const React = require('React');
const {Suspense} = require('React');

const {graphql, usePaginationFragment} = require('react-relay');

type Props = {
  userRef: FriendsListComponent_user$key,
};

function FriendsListComponent(props: Props) {
  const {
    data,
    loadPrevious,
    hasPrevious,
    // ... forward pagination values
  } = usePaginationFragment(
    graphql`
      fragment FriendsListComponent_user on User {
        name
        friends(after: $after, before: $before, first: $first, last: $last)
          @connection(key: "FriendsListComponent_user_friends_connection") {
          edges {
            node {
              name
              age
            }
          }
        }
      }
    `,
    userRef,
  );

  return (
    <>
      <h1>Friends of {data.name}:</h1>
      <List items={data.friends?.edges.map(edge => edge.node)}>
        {node => {
          return (
            <div>
              {node.name} - {node.age}
            </div>
          );
        }}
      </List>

      {hasPrevious ? (
        <Button onClick={() => loadPrevious(10)}>
          Load more friends
        </Button>
      ) : null}

      {/* Forward pagination controls can go simultaneously here */}
    </>
  );
}
```

* The APIs for both *"forward"* and *"backward"* are exactly the same, they're only named differently. When paginating forward, then the  `after` and `first` connection arguments will be used, when paginating backward, the `before` and `last` connection arguments will be used.
* Note that the primitives for both *"forward"* and *"backward"* pagination are exposed from a single call to `usePaginationFragment`, so both *"forward"* and *"backward"* pagination can be performed simultaneously in the same component.

---

### Guided Tour List Data Connections (`website/docs/guided-tour/list-data/connections.mdx`)

---
id: connections
title: Why Connections?
slug: /guided-tour/list-data/connections/
description: Relay guide for connections
keywords:
- pagination
- connections
---

import DocsRating from '@site/src/core/DocsRating';

# Why Connections?

:::info
For a video format of how the connection spec was derived, check out [Sabrina Wasserman's GraphQL talk](../../guides/graphql-server-specification.mdx#graphql-conf-talk)!
:::

Relay does a lot of the work for you when handling paginated collections of items. But to do that, it relies on a specific convention for how those collections are modeled in your schema. This convention is powerful and flexible, and comes out of experience building many products with collections of items. Let’s step through the design process for this schema convention so that we can understand why it works this way.

There are three important points to understand:

* You may need to model data about an item's inclusion in the collection, such as in a list of friends where you may wish to model the date you friended that person. We handle this by creating nodes that represent the edges, the relationship between the item in the collection and the collection itself.
* The page itself has properties, such as whether or not there is a next page available. We handle this with a node that represents the current page info.
* Pagination is done by *cursors* — opaque symbols that point to the next page of results — rather than offsets.

Imagine we want to show a list of the user’s friends. At a high level, we imagine a graph where the viewer and their friends are each nodes. From the viewer to each friend node is an edge, and the edge itself has properties.



Now let’s try to model this situation using GraphQL.

In GraphQL, only nodes can have properties, not edges. So the first thing we’ll do is represent the conceptual edge from you to your friend with its very own node.



Now the properties of the edge are represented by a new type of node called a “`FriendsEdge`”.

The GraphQL to query this would look like this:

```
// XXX example only, not final code
fragment FriendsFragment1 on Viewer {
  friends {
    since // a property of the edge
    node {
      name // a property of the friend itself
    }
  }
}
```

Now we have a good place in the GraphQL schema to put edge-specific information such as the date when the edge was created (that is, the date you friended that person).

* * *

Now consider what we would need to model in our schema in order to support pagination and infinite scrolling.

* The client must be able to specify how large of a page it wants.
* The client must be informed as to whether any more pages are available, so that it can enable or disable the ‘next page’ button (or, for infinite scrolling, can stop making further requests).
* The client must be able to ask for the next page after the one it already has.

How can we use the features of GraphQL to do these things? Specifying the page size is done with field arguments. In other words, instead of just `friends` the query will say `friends(first: 3)`, passing the page size as an argument to the `friends` field.

For the server to say whether there is a next page or not, we need to introduce a node in the graph that has information about the *list of friends itself,* just like we are introducing a node for each edge to store information about the edge itself. This new node is called a *Connection*.

The Connection node represents the connection itself between you and your friends. Metadata about the connection is stored there — for example, it could have a `totalCount` field that says how many friends you have. In addition, it always has two fields which represent the *current* page: a `pageInfo` field with metadata about the current page, such as whether there is another page available — and an `edges` field that points to the edges we saw before:



Finally, we need a way to request the next page of results. You’ll notice in the above diagram that the `PageInfo` node has a field called `lastCursor`.  This is an opaque token provided by the server that represents the position in the list of the last edge that we were given (the friend “Charmaine”). We can then pass this cursor back to the server in order to retrieve the next page.

By passing the `lastCursor` value back to the server as an argument to the `friends` field, we can ask the server for friends that are *after* the ones we’ve already retrieved:



This overall scheme for modeling paginated lists is specified in detail in the [GraphQL Cursor Connections Spec](https://relay.dev/graphql/connections.htm). It is flexible for many different applications, and although Relay relies on this convention to handle pagination automatically, designing your schema this way is a good idea whether or not you use Relay.

Now that we've stepped through the underlying model for Connections, let’s turn our attention to actually using it to implement Comments for our Newsfeed stories.

<DocsRating />

---

### Guided Tour List Data Pagination (`website/docs/guided-tour/list-data/pagination.mdx`)

---
id: pagination
title: Pagination with Connections
slug: /guided-tour/list-data/pagination/
description: Relay guide to connections and pagination
keywords:
- pagination
- connections
- usePaginationFragment
---

import DocsRating from '@site/src/core/DocsRating';

# Pagination with Connections

In order to paginate through lists of data (load only discrete slices of list data), Relay introduces an abstraction known as a "connection". Connections allow you to request discrete slices of data from the server as well as information about the list itself (e.g. how to get the next page of data). For more information about the design of connections, see [Why Connections?](./connections.mdx).

A query with a connection includes:
- the *connection* itself, a field that returns the `edges` and `pageInfo`. It includes a `first` argument to indicate the page size and an `after` argument to indicate where the beginning of the list is.
- the *edge*, which contains the `cursor` (a bookmark of where you are in the list) and the `node` (the actual record the connection is paginating over).
- the *pageInfo*, which contains information about getting more edges (`hasPreviousPage`, `hasNextPage`, `startCursor`, and `endCursor`).

A typical query fragment (for fetching a list of comments) may look like:
```
const StoryCommentsSectionFragment = graphql`
  fragment StoryCommentsSectionFragment on Story {
    # the connection with arguments to specify which items to fetch
    comments(after: $cursor, first: $count) {
      edges {                # the list of edges
        node {               # the Comment record itself
          ...CommentFragment # the fields on Comment to fetch
        }
        cursor               # an identifier of this Comment's place in the list
      }
      pageInfo {             # the page info
        hasNextPage          # if another page of comments is available
      }
    }
  }
`;
```

:::info
Relay uses "cursors" to specify the beginning of a list. Each node is associated with a unique cursor, which can be passed to the connection to fetch the next page _after_ that cursor. This makes it easy to fetch consecutive pages of data.
:::

## Connection Directives

Relay handles a lot of the pagination logic for you but to do so, connections must be augmented with directives containing some additional information.

```
const StoryCommentsSectionFragment = graphql`
  fragment StoryCommentsSectionFragment on Story
  @argumentDefinitions(
    cursor: { type: "String" }
    count: { type: "Int", defaultValue: 3 }
  )
  @refetchable(queryName: "StoryCommentsSectionPaginationQuery") {
    comments(after: $cursor, first: $count)
      @connection(key: "StoryCommentsSectionFragment_comments") {
      edges {
        node {
          ...CommentFragment
        }
        cursor
      }
      pageInfo {
        hasNextPage
        hasPreviousPage
        startCursor
        endCursor
      }
    }
  }
`;
```
Breaking this down:
- `@argumentDefinitions` is just defining the `$cursor` and `$count` variables as [fragment arguments](../../api-reference/graphql/graphql-directives.mdx#argumentdefinitions)
- `@refetchable` makes the fragment [refetchable](../../tutorial/refetchable-fragments.mdx) so that Relay can fetch it again with new arguments — usually, a new cursor for the `$cursor` argument.
- `@connection` is what Relay uses to tell _which field_ within the fragment represents the connection to paginate over. The `@connection` directive requires a `key` argument which must be a unique string — here formed from the fragment name and field name. This key is used when editing the connection’s contents via [mutations](../updating-data/updating-connections.mdx).

:::tip
Relay’s pagination features only work with fragments, not entire queries. This is usually fine as queries are generally issued at some high-level routing component, which would rarely be the same component that’s showing a paginated list. If you need to paginate something at the query level, refactor the connection field out into a fragment that is defined on the `Query` type.
:::

For a full specification of connections, see the [GraphQL Cursor Connections Spec](https://relay.dev/graphql/connections.htm).

## The usePaginationFragment hook

Relay provides an easy way to use connections in React via the [`usePaginationFragment`](../../api-reference/hooks/use-pagination-fragment.mdx) hook. This hook acts similarly to the [`useFragment`](../../api-reference/hooks/use-fragment.mdx) hook but also provides additional callbacks for loading the next/previous page of data along with checking if those pages exist and loading indicators if a request is in flight. Using the `usePaginationFragment` hook also means you can omit the `pageInfo` and `cursor` fields from your fragment as Relay will automatically insert them and use the information to paginate via the hook. Taking the previous example with the `StoryCommentsSectionFragment`, the fragment can be reduced to:

```
const StoryCommentsSectionFragment = graphql`
  fragment StoryCommentsSectionFragment on Story
  @argumentDefinitions(
    cursor: { type: "String" }
    count: { type: "Int", defaultValue: 3 }
  )
  @refetchable(queryName: "StoryCommentsSectionPaginationQuery") {
    comments(after: $cursor, first: $count)
      @connection(key: "StoryCommentsSectionFragment_comments") {
      edges {
        node {
          ...CommentFragment
        }
      }
    }
  }
`;
```

Here's an example of how the `usePaginationFragment` hook can be used to implement pagination in a React component:

```
function StoryCommentsSection({story}) {
  const {
    data,
    hasNext,
    loadNext,
    isLoadingNext,
  } = usePaginationFragment(StoryCommentsSectionFragment, story);
  return (
    <>
      {data.comments.edges.map(commentEdge =>
        <Comment comment={commentEdge.node} />
      )}
      {hasNext && (
        <LoadMoreCommentsButton
          onClick={() => loadNext(3)}
          disabled={isLoadingNext}
        />
      )}
      {isLoadingNext && <SmallSpinner />}
    </>
  );
}
```
In this example, the `story` prop passed to the `usePaginationFragment` is the same as the query reference passed to `useFragment`. Along with the fragment `data`, the hook in this example also returns `loadNext`, `hasNext`, and `isLoadingNext`.
- `hasNext` indicates whether another page of data exists.
- `loadNext` is a function that can be called to load the next page of data — for example when a user clicks on the `LoadMoreCommentsButton`. It takes an argument to indicate how many new items to fetch.
- In order to provide a better user experience, `isLoadingNext` can be used to show a loading indicator while the next page of comments is loading.

:::info
When the request to fetch the next items completes, the connection will be automatically updated and the component will re-render with the latest items in the connection. In our case, this means that the `comments` field will always contain *all* of the comments that we've fetched so far. By default, *Relay will automatically append new items to the connection upon completing a pagination request,* and will make them available to your fragment component*.* If you need a different behavior, check out the [Advanced Pagination Use Cases](./advanced-pagination.mdx) section.
:::

For the full information on the `usePaginationFragment` hook, check out the [API reference](../../api-reference/hooks/use-pagination-fragment.mdx).

## React Loading States

React provides [suspense](https://react.dev/reference/react/Suspense) to allow a fallback while data is loading and [transitions](https://react.dev/reference/react/startTransition) to provide a better user experience when updating data. These can be used in conjunction with `usePaginationFragment`.

Taking the example above,
```
function StoryCommentsSection({story}) {
  const {
    data,
    hasNext,
    loadNext,
    isLoadingNext,
  } = usePaginationFragment(StoryCommentsSectionFragment, story);
  return (
    <>
      {data.comments.edges.map(commentEdge => {
        return (
          <Suspense fallback={<Glimmer />}>
            <Comment comment={commentEdge.node} />
          </Suspense>
        );
      })}
      {hasNext && (
        <LoadMoreCommentsButton
          onClick={() => {
            startTransition(() => {
              loadNext(3)
            });
          }}
          disabled={isLoadingNext}
        />
      )}
      {isLoadingNext && <SmallSpinner />}
    </>
  );
}
```

Calling `loadNext` may cause the component or new children components to suspend (as explained in [Loading States with Suspense](../rendering/loading-states.mdx)). This means that you'll need to make sure that there's a `Suspense` boundary wrapping this component from above and/or that you are using a transition in order to show the appropriate pending or loading state.

:::note
Since `loadNext` may cause the component to suspend, regardless of whether a transition is used to render a pending state (i.e. with a loading indicator from [useTransition](https://react.dev/reference/react/useTransition)), `startTransition` should always be used to schedule that update for the best user experience.
:::

<DocsRating />

---

### Guided Tour List Data Rendering Connections (`website/docs/guided-tour/list-data/rendering-connections.mdx`)

---
id: rendering-connections
title: Rendering Connections
slug: /guided-tour/list-data/rendering-connections/
description: Relay guide to rendering connections
keywords:
- pagination
- usePaginationFragment
- connection
---

import DocsRating from '@site/src/core/DocsRating';
// @fb-only
// @fb-only
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

In Relay, in order to display a list of data that is backed by a GraphQL connection, first you need to declare a fragment that queries for a connection:

```js
const {graphql} = require('RelayModern');

const userFragment = graphql`
  fragment UserFragment on User {
    name
    friends(after: $cursor, first: $count)
      @connection(key: "UserFragment_friends") {
      edges {
        node {
          ...FriendComponent
        }
      }
    }
  }
`;
```

* In the example above, we're querying for the `friends` field, which is a connection; in other words, it adheres to the connection spec. Specifically, we can query the `edges` and `node`s in the connection; the `edges` usually contain information about the relationship between the entities, while the `node`s are the actual entities at the other end of the relationship; in this case, the `node`s are objects of type `User` representing the user's friends.
* In order to indicate to Relay that we want to perform pagination over this connection, we need to mark the field with the `@connection` directive. We must also provide a *static* unique identifier for this connection, known as the `key`. We recommend the following naming convention for the connection key: `<fragment_name>_<field_name>`.
* We will go into more detail later as to why it is necessary to mark the field as a `@connection` and give it a unique `key` in our [Updating Connections](../updating-connections/) section.


In order to render this fragment which queries for a connection, we can use the `usePaginationFragment` Hook:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

```js
import type {FriendsListComponent_user$key} from 'FriendsList_user.graphql';

const React = require('React');
const {Suspense} = require('React');

const {graphql, usePaginationFragment} = require('react-relay');

type Props = {
  user: FriendsListComponent_user$key,
};

function FriendsListComponent(props: Props) {
  const {data} = usePaginationFragment(
    graphql`
      fragment FriendsListComponent_user on User
      @refetchable(queryName: "FriendsListPaginationQuery") {
        name
        friends(first: $count, after: $cursor)
        @connection(key: "FriendsList_user_friends") {
          edges {
            node {
              ...FriendComponent
            }
          }
        }
      }
    `,
    props.user,
  );


  return (
    <>
      {data.name != null ? <h1>Friends of {data.name}:</h1> : null}

      <div>
        {/* Extract each friend from the resulting data */}
        {(data.friends?.edges ?? []).map(edge => {
          const node = edge.node;
          return (
            <Suspense fallback={<Glimmer />}>
              <FriendComponent user={node} />
            </Suspense>
          );
        })}
      </div>
    </>
  );
}

module.exports = FriendsListComponent;
```
// @fb-only

* `usePaginationFragment` behaves the same way as a `useFragment` (see the [Fragments](../../rendering/fragments/) section), so our list of friends is available under `data.friends.edges.node`, as declared by the fragment. However, it also has a few additions:
    * It expects a fragment that is a connection field annotated with the `@connection` directive
    * It expects a fragment that is annotated with the `@refetchable` directive. Note that  `@refetchable` directive can only be added to fragments that are "refetchable", that is, on fragments that are on `Viewer`, on `Query`, on any type that implements `Node` (i.e. a type that has an `id` field), or on a `@fetchable` type. <FbInternalOnly> For more info on `@fetchable` types, see [this post](https://fb.workplace.com/groups/graphql.fyi/permalink/1539541276187011/). </FbInternalOnly>
* It takes two Flow type parameters: the type of the generated query (in our case  `FriendsListPaginationQuery`), and a second type which can always be inferred, so you only need to pass underscore (`_`).

</OssOnly>

<DocsRating />

---

### Guided Tour List Data Streaming Pagination (`website/docs/guided-tour/list-data/streaming-pagination.mdx`)

---
id: streaming-pagination
title: Streaming Pagination
slug: /guided-tour/list-data/streaming-pagination/
description: Relay guide to streaming pagination
keywords:
- pagination
- usePaginationFragment
- connection
- streaming
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

<FbInternalOnly>

Additionally, we can combine `usePaginationFragment` with Relay's [Incremental Data Delivery](../../../guides/incremental-data-delivery/) capabilities in order to fetch a connection and incrementally receive each item in the connection as it becomes ready, instead of waiting for the whole list of items to be returned in a single payload. This can be useful when for example computing each item in the connection is an expensive operation in the server, and we want to be able to show the first item(s) in the list as soon as possible without blocking on *all* the items that we need to become available; for example, on News Feed a user could ideally see and start interacting with the first story while additional stories loaded in below.

</FbInternalOnly>

<OssOnly>

Additionally, we can combine `usePaginationFragment` with Relay's Incremental Data Delivery capabilities in order to fetch a connection and incrementally receive each item in the connection as it becomes ready, instead of waiting for the whole list of items to be returned in a single payload. This can be useful when for example computing each item in the connection is an expensive operation in the server, and we want to be able to show the first item(s) in the list as soon as possible without blocking on *all* the items that we need to become available; for example, on News Feed a user could ideally see and start interacting with the first story while additional stories loaded in below.

</OssOnly>

In order to do so, we can use the `@stream_connection` directive instead of the `@connection` directive:

```js
import type {FriendsListComponent_user$key} from 'FriendsList_user.graphql';

const React = require('React');

const {graphql, usePaginationFragment} = require('react-relay');

type Props = {
  user: FriendsListComponent_user$key,
};

function FriendsListComponent(props: Props) {
  // ...

  const {
    data,
    loadNext,
    hasNext,
  } = usePaginationFragment(
    graphql`
      fragment FriendsListComponent_user on User
      @refetchable(queryName: "FriendsListPaginationQuery") {
        name
        friends(first: $count, after: $cursor)
        @stream_connection(key: "FriendsList_user_friends", initial_count: 2,) {
          edges {
            node {
              name
              age
            }
          }
        }
      }
    `,
    props.user,
  );

  return (...);
}

module.exports = FriendsListComponent;
```

Let's distill what's happening here:

* The `@stream_connection` directive can be used directly in place of the `@connection` directive; it accepts the same arguments as @connection plus additional, *optional* parameters to control streaming:
    * `initial_count: Int`: A number (defaulting to zero) that controls how many items will be included in the initial payload. Any subsequent items are streamed, so when set to zero the list will initially be empty and all items will be streamed. Note that this number does not affect how many items are returned *total*, only how many items are included in the initial payload. For example, consider a product that today makes an initial fetch for 2 items and then *immediately* issues a pagination query to fetch 3 more. With streaming, this product could instead choose to fetch 5 items in the initial query with initial_count=2, in order to fetch the 2 items quickly while avoiding a round trip for the subsequent 3 items.
* As with regular usage of `usePaginationFragment`, the connection will be automatically updated as new items are streamed in from the server, and the component will re-render each time with the latest items in the connection.


<FbInternalOnly>

For more information, see our docs on [Incremental Data Delivery](../../../guides/incremental-data-delivery/#stream_connection).

</FbInternalOnly>


<DocsRating />

---

### Guided Tour Managing Data Outside React Retaining Queries (`website/docs/guided-tour/managing-data-outside-react/retaining-queries.mdx`)

---
id: retaining-queries
title: Retaining Queries
slug: /guided-tour/accessing-data-without-react/retaining-queries/
description: Relay guide to retaining queries
keywords:
- retaining
- query
- environment
- garbage collection
- gc
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

In order to manually retain a query so that the data it references isn’t garbage collected by Relay, we can use the `environment.retain` method:

```js
const {
  createOperationDescriptor,
  getRequest,
  graphql,
} = require('relay-runtime')

// Query graphql object
const query = graphql`...`;

// Construct Relay's internal representation of the query
const queryRequest = getRequest(query);
const queryDescriptor = createOperationDescriptor(
  queryRequest,
  variables
);

// Retain query; this will prevent the data for this query and
// variables from being garbage collected by Relay
const disposable = environment.retain(queryDescriptor);

// Disposing of the disposable will release the data for this query
// and variables, meaning that it can be deleted at any moment
// by Relay's garbage collection if it hasn't been retained elsewhere
disposable.dispose();
```

:::note
Relay automatically manages the query data retention based on any mounted query components that are rendering the data, so you usually should not need to call retain directly within product code. For any advanced or special use cases, query data retention should usually be handled within infra-level code, such as a Router.
:::


<DocsRating />

---

### Guided Tour Refetching Refetching Queries With Different Data (`website/docs/guided-tour/refetching/refetching-queries-with-different-data.mdx`)

---
id: refetching-queries-with-different-data
title: Refetching Queries with Different Data
slug: /guided-tour/refetching/refetching-queries-with-different-data/
description: Relay guide to refetching queries with different data
keywords:
- refetching
- query
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
// @fb-only
// @fb-only
// @fb-only

When referring to **"refetching a query"**, we mean fetching the query again for *different* data than was originally rendered by the query. For example, this might be to change a currently selected item, to render a different list of items than the one being shown, or more generally to transition the currently rendered content to show new or different content.

## When using `useQueryLoader` / `loadQuery`

Similarly to [Refreshing Queries with `useQueryLoader`](../refreshing-queries/#when-using-usequeryloader--loadquery), we can also use the `useQueryLoader` Hook described in our [Fetching Queries for Render](../../rendering/queries/#fetching-queries-for-render) section, but this time passing *different query variables*:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

```js
/**
 * App.react.js
 */
const AppQuery = require('__generated__/AppQuery.graphql');

function App(props: Props) {
  const variables = {id: '4'};
  const [queryRef, loadQuery] = useQueryLoader(
    AppQuery,
    props.appQueryRef /* initial query ref */
  );

  const refetch = useCallback(() => {
    // Load the query again using the same original variables.
    // Calling loadQuery will update the value of queryRef.
    loadQuery({id: 'different-id'});
  }, [/* ... */]);

  return (
    <React.Suspense fallback="Loading query...">
      <MainContent
        refetch={refetch}
        queryRef={queryRef}
      />
    </React.Suspense>
  );
}
```

```js
/**
 * MainContent.react.js
 */

// Renders the preloaded query, given the query reference
function MainContent(props) {
  const {refetch, queryRef} = props;
  const data = usePreloadedQuery(
    graphql`
      query AppQuery($id: ID!) {
        user(id: $id) {
          name
          friends {
            count
          }
        }
      }
    `,
    queryRef,
  );

  return (
    <>
      <h1>{data.user?.name}</h1>
      <div>Friends count: {data.user?.friends?.count}</div>
      <Button
        onClick={() => refetch()}>
        Fetch latest count
      </Button>
    </>
  );
}
```

Let's distill what's going on here:

* We call `loadQuery` in the event handler for refetching, so the network request starts immediately, and then pass the `queryRef` to `usePreloadedQuery`, so it renders the updated data.
* We are not passing a `fetchPolicy` to `loadQuery`, meaning that it will use the default value of `'store-or-network'`. We could provide a different policy in order to specify whether to use locally cached data (as we covered in [Reusing Cached Data For Render](../../reusing-cached-data/)).
* Calling `loadQuery` will re-render the component and may cause `usePreloadedQuery` to suspend (as explained in [Loading States with Suspense](../../rendering/loading-states/)). This means that we'll need to make sure that there's a `Suspense` boundary wrapping the `MainContent` component, in order to show a fallback loading state.

</OssOnly>


### If you need to avoid Suspense

In some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use [`fetchQuery`](../../../api-reference/fetch-query/) instead, and manually keep track of a loading state:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

```js
/**
 * App.react.js
 */
const AppQuery = require('__generated__/AppQuery.graphql');

function App(props: Props) {
  const environment = useRelayEnvironment();
  const [queryRef, loadQuery] = useQueryLoader(
    AppQuery,
    props.appQueryRef /* initial query ref */
  );
  const [isRefetching, setIsRefetching] = useState(false)

  const refetch = useCallback(() => {
    if (isRefetching) { return; }
    setIsRefetching(true);
    const variables = { id: 'different-id' };

    // fetchQuery will fetch the query and write
    // the data to the Relay store. This will ensure
    // that when we re-render, the data is already
    // cached and we don't suspend
    fetchQuery(environment, AppQuery, variables)
      .subscribe({
        complete: () => {
          setIsRefetching(false);

          // *After* the query has been fetched, we call
          // loadQuery again to re-render with a new
          // queryRef.
          // At this point the data for the query should
          // be cached, so we use the 'store-only'
          // fetchPolicy to avoid suspending.
          loadQuery(variables, {fetchPolicy: 'store-only'});
        },
        error: () => {
          setIsRefetching(false);
        }
      });
  }, [/* ... */]);

  return (
    <React.Suspense fallback="Loading query...">
      <MainContent
        isRefetching={isRefetching}
        refetch={refetch}
        queryRef={queryRef}
      />
    </React.Suspense>
  );
}
```

Let's distill what's going on here:

* When refetching, we now keep track of our own `isRefetching` loading state, since we are avoiding suspending. We can use this state to render a busy spinner or similar loading UI inside the `MainContent` component, *without* hiding the `MainContent`.
* In the event handler, we first call `fetchQuery`, which will fetch the query and write the data to the local Relay store. When the `fetchQuery` network request completes, we call `loadQuery` so that we obtain an updated `queryRef` that we then pass to `usePreloadedQuery` in order render the updated data, similar to the previous example.
* At this point, when `loadQuery` is called, the data for the query should already be cached in the local Relay store, so we use `fetchPolicy` of `'store-only'` to avoid suspending and only read the already cached data.

## When using `useLazyLoadQuery`

Similarly to [Refreshing Queries with `useLazyLoadQuery`](../refreshing-queries/#when-using-uselazyloadquery), we can also use the [`useLazyLoadQuery`](../../../api-reference/use-lazy-load-query/) Hook described in our [Lazily Fetching Queries during Render](../../rendering/queries/#lazily-fetching-queries-during-render) section, but this time passing *different query variables*:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

```js
/**
 * App.react.js
 */
const AppQuery = require('__generated__/AppQuery.graphql');

function App(props: Props) {
  const [queryArgs, setQueryArgs] = useState({
    options: {fetchKey: 0},
    variables: {id: '4'},
  });

  const refetch = useCallback(() => {
    // Trigger a re-render of useLazyLoadQuery with new variables,
    // *and* an updated fetchKey.
    // The new fetchKey will ensure that the query is fully
    // re-evaluated and refetched.
    setQueryArgs(prev => ({
      options: {
        fetchKey: (prev?.options.fetchKey ?? 0) + 1,
      },
      variables: {id: 'different-id'}
    }));
  }, [/* ... */]);

  return (
    <React.Suspense fallback="Loading query...">
      <MainContent
        refetch={refetch}
        queryArgs={queryArgs}
      />
    </React.Suspense>
  );
}
```

```js
/**
 * MainContent.react.js
 */
// Fetches and renders the query, given the fetch options
function MainContent(props) {
  const {refetch, queryArgs} = props;
  const data = useLazyLoadQuery(
    graphql`
      query AppQuery($id: ID!) {
        user(id: $id) {
          name
          friends {
            count
          }
        }
      }
    `,
    queryArgs.variables,
    queryArgs.options,
  );

  return (
    <>
      <h1>{data.user?.name}</h1>
      <div>Friends count: {data.user.friends?.count}</div>
      <Button
        onClick={() => refetch()}>
        Fetch latest count
      </Button>
    </>
  );
}
```

Let's distill what's going on here:

* We update the component in the event handler for refreshing by setting new query args in state. This will cause the `MainContent` component that uses `useLazyLoadQuery` to re-render with the new `variables` and  `fetchKey`, and refetch the query upon rendering.
* We are passing a new value of `fetchKey` which we increment on every update. Passing a new `fetchKey` to `useLazyLoadQuery` on every update will ensure that the query is fully re-evaluated and refetched.
* We are not passing a new `fetchPolicy` to `useLazyLoadQuery`, meaning that it will use the default value of `'store-or-network'`. We could provide a different policy in order to specify whether to use locally cached data (as we covered in [Reusing Cached Data For Render](../../reusing-cached-data/)).
* The state update in `refetch` will re-render the component and may cause the component to suspend (as explained in [Loading States with Suspense](../../rendering/loading-states/)). This means that we'll need to make sure that there's a `Suspense` boundary wrapping the `MainContent` component, in order to show a fallback loading state.


</OssOnly>

### If you need to avoid Suspense

In some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use [`fetchQuery`](../../../api-reference/fetch-query/) instead, and manually keep track of a loading state:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

```
/* Detailed source-code truncated for AI context efficiency. */
```

Let's distill what's going on here:

* When refetching, we now keep track of our own `isRefetching` loading state, since we are avoiding suspending. We can use this state to render a busy spinner or similar loading UI inside the `MainContent` component, *without* hiding the `MainContent`.
* In the event handler, we first call `fetchQuery`, which will fetch the query and write the data to the local Relay store. When the `fetchQuery` network request completes, we update our state so that we re-render an updated `fetchKey` and `fetchPolicy` that we then pass to `useLazyLoadQuery` in order render the updated data, similar to the previous example.
* At this point, when we update the state, the data for the query should already be cached in the local Relay store, so we use `fetchPolicy` of `'store-only'` to avoid suspending and only read the already cached data.


<DocsRating />

---

### Guided Tour Refetching Refreshing Queries (`website/docs/guided-tour/refetching/refreshing-queries.mdx`)

---
id: refreshing-queries
title: Refreshing Queries
slug: /guided-tour/refetching/refreshing-queries/
description: Relay guide to refreshing queries
keywords:
- refreshing
- queries
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
// @fb-only
// @fb-only
// @fb-only
// @fb-only

When referring to **"refreshing a query"**, we mean fetching the *exact* same data that was originally rendered by the query, in order to get the most up-to-date version of that data from the server.

## Using real-time features

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

If we want to keep our data up to date with the latest version from the server, the first thing to consider is if it appropriate to use any real-time features, which can make it easier to automatically keep the data up to date without manually refreshing the data periodically.

One example of this is using [GraphQL Subscriptions](https://relay.dev/docs/guided-tour/updating-data/graphql-subscriptions), which will require additional configuration on your server and [network layer](https://relay.dev/docs/guided-tour/updating-data/graphql-subscriptions/#configuring-the-network-layer).

</OssOnly>

## When using `useQueryLoader` / `loadQuery`

To refresh a query using the [`useQueryLoader`](../../../api-reference/use-query-loader/) Hook described in our [Fetching Queries for Render](../../rendering/queries/#fetching-queries-for-render) section, we only need to call `loadQuery` again:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

```js
/**
 * App.react.js
 */

const AppQuery = require('__generated__/AppQuery.graphql');

function App(props: Props) {
  const [queryRef, loadQuery] = useQueryLoader(
    AppQuery,
    props.appQueryRef /* initial query ref */
  );

  const refresh = useCallback(() => {
    // Load the query again using the same original variables.
    // Calling loadQuery will update the value of queryRef.
    // The fetchPolicy ensures we always fetch from the server and skip
    // the local data cache.
    const {variables} = props.appQueryRef;
    loadQuery(variables, {fetchPolicy: 'network-only'});
  }, [/* ... */]);

  return (
    <React.Suspense fallback="Loading query...">
      <MainContent
        refresh={refresh}
        queryRef={queryRef}
      />
    </React.Suspense>
  );
}
```

```js
/**
 * MainContent.react.js
 */

// Renders the preloaded query, given the query reference
function MainContent(props) {
  const {refresh, queryRef} = props;
  const data = usePreloadedQuery(
    graphql`
      query AppQuery($id: ID!) {
        user(id: $id) {
          name
          friends {
            count
          }
        }
      }
    `,
    queryRef,
  );

  return (
    <>
      <h1>{data.user?.name}</h1>
      <div>Friends count: {data.user.friends?.count}</div>
      <Button
        onClick={() => refresh()}>
        Fetch latest count
      </Button>
    </>
  );
}
```

Let's distill what's going on here:

* We call `loadQuery` in the event handler for refreshing, so the network request starts immediately, and then pass the updated `queryRef` to the `MainContent` component that uses `usePreloadedQuery`, so it renders the updated data.
* We are passing a `fetchPolicy` of `'network-only'` to ensure that we always fetch from the network and skip the local data cache.
* Calling `loadQuery` will re-render the component and cause `usePreloadedQuery` to suspend (as explained in [Loading States with Suspense](../../rendering/loading-states/)), since a network request will always be made due to the `fetchPolicy` we are using. This means that we'll need to make sure that there's a `Suspense` boundary wrapping the `MainContent` component in order to show a fallback loading state.

</OssOnly>

### If you need to avoid Suspense

In some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use [`fetchQuery`](../../../api-reference/fetch-query/) instead, and manually keep track of a loading state:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

```js
/**
 * App.react.js
 */

const AppQuery = require('__generated__/AppQuery.graphql');

function App(props: Props) {
  const environment = useRelayEnvironment();
  const [queryRef, loadQuery] = useQueryLoader(
    AppQuery,
    props.appQueryRef /* initial query ref */
  );
  const [isRefreshing, setIsRefreshing] = useState(false)

  const refresh = useCallback(() => {
    if (isRefreshing) { return; }
    const {variables} = props.appQueryRef;
    setIsRefreshing(true);

    // fetchQuery will fetch the query and write
    // the data to the Relay store. This will ensure
    // that when we re-render, the data is already
    // cached and we don't suspend
    fetchQuery(environment, AppQuery, variables)
      .subscribe({
        complete: () => {
          setIsRefreshing(false);

          // *After* the query has been fetched, we call
          // loadQuery again to re-render with a new
          // queryRef.
          // At this point the data for the query should
          // be cached, so we use the 'store-only'
          // fetchPolicy to avoid suspending.
          loadQuery(variables, {fetchPolicy: 'store-only'});
        }
        error: () => {
          setIsRefreshing(false);
        }
      });
  }, [/* ... */]);

  return (
    <React.Suspense fallback="Loading query...">
      <MainContent
        isRefreshing={isRefreshing}
        refresh={refresh}
        queryRef={queryRef}
      />
    </React.Suspense>
  );
}
```

Let's distill what's going on here:

* When refreshing, we now keep track of our own `isRefreshing` loading state, since we are avoiding suspending. We can use this state to render a busy spinner or similar loading UI inside the `MainContent` component, *without* hiding the `MainContent`.
* In the event handler, we first call `fetchQuery`, which will fetch the query and write the data to the local Relay store. When the `fetchQuery` network request completes, we call `loadQuery` so that we obtain an updated  `queryRef` that we then pass to `usePreloadedQuery` in order render the updated data, similar to the previous example.
* At this point, when `loadQuery` is called, the data for the query should already be cached in the local Relay store, so we use `fetchPolicy` of `'store-only'` to avoid suspending and only read the already cached data.


## When using `useLazyLoadQuery`

To refresh a query using the [`useLazyLoadQuery`](../../../api-reference/use-lazy-load-query/) Hook described in our [Lazily Fetching Queries during Render](../../rendering/queries/#lazily-fetching-queries-during-render) section, we can do the following:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

```js
/**
 * App.react.js
 */
const AppQuery = require('__generated__/AppQuery.graphql');

function App(props: Props) {
  const variables = {id: '4'};
  const [refreshedQueryOptions, setRefreshedQueryOptions] = useState(null);

  const refresh = useCallback(() => {
    // Trigger a re-render of useLazyLoadQuery with the same variables,
    // but an updated fetchKey and fetchPolicy.
    // The new fetchKey will ensure that the query is fully
    // re-evaluated and refetched.
    // The fetchPolicy ensures that we always fetch from the network
    // and skip the local data cache.
    setRefreshedQueryOptions(prev => ({
      fetchKey: (prev?.fetchKey ?? 0) + 1,
      fetchPolicy: 'network-only',
    }));
  }, [/* ... */]);

  return (
    <React.Suspense fallback="Loading query...">
      <MainContent
        refresh={refresh}
        queryOptions={refreshedQueryOptions ?? {}}
        variables={variables}
      />
    </React.Suspense>
  );
```

```js
/**
 * MainContent.react.js
 */

// Fetches and renders the query, given the fetch options
function MainContent(props) {
  const {refresh, queryOptions, variables} = props;
  const data = useLazyLoadQuery(
    graphql`
      query AppQuery($id: ID!) {
        user(id: $id) {
          name
          friends {
            count
          }
        }
      }
    `,
    variables,
    queryOptions,
  );

  return (
    <>
      <h1>{data.user?.name}</h1>
      <div>Friends count: {data.user.friends?.count}</div>
      <Button
        onClick={() => refresh()}>
        Fetch latest count
      </Button>
    </>
  );
}
```

Let's distill what's going on here:

* We update the component in the event handler for refreshing by setting new options in state. This will cause the `MainContent` component that uses `useLazyLoadQuery` to re-render with the new `fetchKey` and `fetchPolicy`, and refetch the query upon rendering.
* We are passing a new value of `fetchKey` which we increment on every update. Passing a new `fetchKey` to `useLazyLoadQuery` on every update will ensure that the query is fully re-evaluated and refetched.
* We are passing a `fetchPolicy` of `'network-only'` to ensure that we always fetch from the network and skip the local data cache.
* The state update in `refresh` will cause the component to suspend (as explained in [Loading States with Suspense](../../rendering/loading-states/)), since a network request will always be made due to the `fetchPolicy` we are using. This means that we'll need to make sure that there's a `Suspense` boundary wrapping the `MainContent` component in order to show a fallback loading state.

</OssOnly>

### If you need to avoid Suspense

In some cases, you might want to avoid showing a Suspense fallback, which would hide the already rendered content. For these cases, you can use [`fetchQuery`](../../../api-reference/fetch-query/) instead, and manually keep track of a loading state:

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

```
/* Detailed source-code truncated for AI context efficiency. */
```

Let's distill what's going on here:

* When refreshing, we now keep track of our own `isRefreshing` loading state, since we are avoiding suspending. We can use this state to render a busy spinner or similar loading UI inside the `MainContent` component, *without* hiding the `MainContent`.
* In the event handler, we first call `fetchQuery`, which will fetch the query and write the data to the local Relay store. When the `fetchQuery` network request completes, we update our state so that we re-render an updated `fetchKey` and `fetchPolicy` that we then pass to `useLazyLoadQuery` in order render the updated data, similar to the previous example.
* At this point, when we update the state, the data for the query should already be cached in the local Relay store, so we use `fetchPolicy` of `'store-only'` to avoid suspending and only read the already cached data.

<DocsRating />

---

### Guided Tour Rendering Environment (`website/docs/guided-tour/rendering/environment.mdx`)

---
id: environment
title: Environment
slug: /guided-tour/rendering/environment/
description: Relay guide to the environment
keywords:
- environment
- RelayEnvironmentProvider
- useRelayEnvironment
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
// @fb-only
// @fb-only

## Relay Environment Provider

In order to render Relay components, you need to render a `RelayEnvironmentProvider` component at the root of the app:

```js
// App root

const {RelayEnvironmentProvider} = require('react-relay');
const Environment = require('MyEnvironment');

function Root() {
  return (
    <RelayEnvironmentProvider environment={Environment}>
      {/*... */}
    </RelayEnvironmentProvider>
  );
}
```

* The `RelayEnvironmentProvider` takes an environment, which it will make available to all descendant Relay components, and which is necessary for Relay to function.

// @fb-only

## Accessing the Relay Environment

If you want to access the *current* Relay Environment within a descendant of a `RelayEnvironmentProvider` component, you can use the `useRelayEnvironment` Hook:

```js
const {useRelayEnvironment} = require('react-relay');

function UserComponent(props: Props) {
  const environment = useRelayEnvironment();

  return (...);
}
```


// @fb-only



<DocsRating />

---

### Guided Tour Rendering Error States (`website/docs/guided-tour/rendering/error-states.mdx`)

---
id: error-states
title: Error States with ErrorBoundaries
slug: /guided-tour/rendering/error-states/
description: Relay guide to rendering error states
keywords:
- rendering
- error
- boundary
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
// @fb-only

// @fb-only

As you may have noticed, we mentioned that using `usePreloadedQuery` will render data from a query that was (or is) being fetched from the server, but we didn't elaborate on how to render UI to show an error if an error occurred during fetch. We will cover that in this section.

We can use [Error Boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) components to catch errors that occur during render (due to a network error, or any kind of error), and render an alternative error UI when that occurs. The way it works is similar to how `Suspense` works, by wrapping a component tree in an error boundary, we can specify how we want to react when an error occurs, for example by rendering a fallback UI.

[Error boundaries](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) are simply components that implement the static `getDerivedStateFromError` method:

```js
const React = require('React');

type State = {error: ?Error};

class ErrorBoundary extends React.Component<Props, State> {
  static getDerivedStateFromError(error): State {
    // Set some state derived from the caught error
    return {error: error};
  }
}
```

```js
/**
 * App.react.js
 */

const ErrorBoundary = require('ErrorBoundary');
const React = require('React');

const MainContent = require('./MainContent.react');
const SecondaryContent = require('./SecondaryContent.react');

function App() {
  return (
    // Render an ErrorSection if an error occurs within
    // MainContent or Secondary Content
    <ErrorBoundary fallback={error => <ErrorUI error={error} />}>
      <MainContent />
      <SecondaryContent />
    </ErrorBoundary>
  );
}
```

* We can use the Error Boundary to wrap subtrees and show a different UI when an error occurs within that subtree. When an error occurs, the specified `fallback` will be rendered instead of the content inside the boundary.
* Note that we can also control the granularity at which we render error UIs, by wrapping components at different levels with error boundaries. In this example, if any error occurs within `MainContent` or `SecondaryContent`, we will render an `ErrorSection` in place of the entire app content.



## Retrying after an Error

### When using `useQueryLoader` / `loadQuery`

When using `useQueryLoader`/`loadQuery` to fetch a query, in order to retry after an error has occurred, you can call `loadQuery` again and pass the *new* query reference to `usePreloadedQuery`:

```js
/**
 * ErrorBoundaryWithRetry.react.js
 */

const React = require('React');

// NOTE: This is NOT actual production code;
// it is only used to illustrate example
class ErrorBoundaryWithRetry extends React.Component<Props, State> {
  state = {error: null};

  static getDerivedStateFromError(error): State {
    return {error: error};
  }

  _retry = () => {
    // This ends up calling loadQuery again to get and render
    // a new query reference
    this.props.onRetry();
    this.setState({
      // Clear the error
      error: null,
    });
  }

  render() {
    const {children, fallback} = this.props;
    const {error} = this.state;
    if (error) {
      if (typeof fallback === 'function') {
        return fallback({error, retry: this._retry});
      }
      return fallback;
    }
    return children;
  }
}
```
* When an error occurs, we render the provided `fallback`.
* When `retry` is called, we will clear the error, and call `loadQuery` again. This will fetch the query again and provide us a new query reference, which we can then pass down to `usePreloadedQuery`.

```js
/**
 * App.react.js
 */

const ErrorBoundaryWithRetry = require('ErrorBoundaryWithRetry');
const React = require('React');

const MainContent = require('./MainContent.react');

const query = require('__generated__/MainContentQuery.graphql');

// NOTE: This is NOT actual production code;
// it is only used to illustrate example
function App(props) {
  // E.g., initialQueryRef provided by router
  const [queryRef, loadQuery] = useQueryLoader(query, props.initialQueryRef);

  return (
    <ErrorBoundaryWithRetry
      // On retry we call loadQuery again, which will update
      // the value of queryRef from useQueryLoader with a new
      // fresh query reference
      onRetry={() => loadQuery(/* ... */)}
      fallback={({error, retry}) =>
        <>
          <ErrorUI error={error} />
          {/* Render a button to retry; this will attempt to re-render the
          content inside the boundary, i.e. the query component */}
          <Button onPress={retry}>Retry</Button>
        </>
      }>
      {/* The value of queryRef will be updated after calling
      loadQuery again */}
      <MainContent queryRef={queryRef} />
    </ErrorBoundaryWithRetry>
  );
}

/**
 * MainContent.react.js
 */
function MainContent(props) {
  const data = usePreloadedQuery(
    graphql`...`,
    props.queryRef
  );

  return (/* ... */);
}
```
* The sample Error Boundary in this example code will provide a `retry` function to the `fallback` which we can use to clear the error, re-load the query, and re-render with a new query ref that we can pass to the component that uses `usePreloadedQuery`. That component will consume the new query ref and suspend if necessary on the new network request.


### When using `useLazyLoadQuery`

When using `useLazyLoadQuery` to fetch a query, in order to retry after an error has occurred, you can attempt to re-mount *and* re-evaluate the query component by passing it a new `fetchKey`:

```js
/**
 * ErrorBoundaryWithRetry.react.js
 */

const React = require('React');

// NOTE: This is NOT actual production code;
// it is only used to illustrate example
class ErrorBoundaryWithRetry extends React.Component<Props, State> {
  state = {error: null, fetchKey: 0};

  static getDerivedStateFromError(error): State {
    return {error: error, fetchKey: 0};
  }

  _retry = () => {
    this.setState(prev => ({
      // Clear the error
      error: null,
      // Increment and set a new fetchKey in order
      // to trigger a re-evaluation and refetching
      // of the query using useLazyLoadQuery
      fetchKey: prev.fetchKey + 1,
    }));
  }

  render() {
    const {children, fallback} = this.props;
    const {error, fetchKey} = this.state;
    if (error) {
      if (typeof fallback === 'function') {
        return fallback({error, retry: this._retry});
      }
      return fallback;
    }
    return children({fetchKey});
  }
}
```
* When an error occurs, we render the provided `fallback`.
* When `retry` is called, we will clear the error, and increment our `fetchKey` which we can then pass down to `useLazyLoadQuery`. This will make it so we re-render the component that uses `useLazyLoadQuery` with a new `fetchKey`, ensuring that the query is refetched upon the new call to `useLazyLoadQuery`.

```js
/**
 * App.react.js
 */

const ErrorBoundaryWithRetry = require('ErrorBoundaryWithRetry');
const React = require('React');

const MainContent = require('./MainContent.react');

// NOTE: This is NOT actual production code;
// it is only used to illustrate example
function App() {
  return (
    <ErrorBoundaryWithRetry
      fallback={({error, retry}) =>
        <>
          <ErrorUI error={error} />
          {/* Render a button to retry; this will attempt to re-render the
            content inside the boundary, i.e. the query component */}
          <Button onPress={retry}>Retry</Button>
        </>
      }>
      {({fetchKey}) => {
        // If we have retried, use the new `retryQueryRef` provided
        // by the Error Boundary
        return <MainContent fetchKey={fetchKey} />;
      }}
    </ErrorBoundaryWithRetry>
  );
}

/**
 * MainContent.react.js
 */
function MainContent(props) {
  const data = useLazyLoadQuery(
    graphql`...`,
    variables,
    {fetchKey: props.fetchKey}
  );

  return (/* ... */);
}
```
* The sample Error Boundary in this example code will provide a `retry` function to the `fallback` which we can use to clear the error and re-render `useLazyLoadQuery` with a new `fetchKey`. This will cause the query to be re-evaluated and refetched, and `useLazyLoadQuery` start a new network request and suspend.



## Accessing errors in GraphQL Responses


<FbInternalOnly>

By default, internally at fb, Relay will *only* surface errors to React that are returned in the top-level [`errors` field](https://graphql.org/learn/validation/) if they are either:

* of `CRITICAL` severity,
*  *or* if the top-level `data` field wasn't returned in the response.

</FbInternalOnly>


If you wish to access error information in your application to display user friendly messages, the recommended approach is to model and expose the error information as part of your GraphQL schema.

For example, you could expose a field in your schema that returns either the expected result, or an Error object if an error occurred while resolving that field (instead of returning null):


```js
type Error {
  # User friendly message
  message: String!
}

type Foo {
  bar: Result | Error
}
```




<DocsRating />

---

### Guided Tour Rendering Fragments (`website/docs/guided-tour/rendering/fragments.mdx`)

---
id: fragments
title: Fragments
slug: /guided-tour/rendering/fragments/
description: Relay guide to rendering fragments
keywords:
- useFragment
- rendering
- fragment
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

The main building block for declaring data dependencies for React Components in Relay are [GraphQL Fragments](https://graphql.org/learn/queries/#fragments). Fragments are reusable units in GraphQL that represent a set of data to query from a GraphQL type exposed in the [schema](https://graphql.org/learn/schema/).

In practice, they are a selection of fields on a GraphQL Type:

```graphql
fragment UserFragment on User {
  name
  age
  profile_picture(scale: 2) {
    uri
  }
}
```


In order to declare a fragment inside your JavaScript code, you must use the `graphql` tag:

```js
const {graphql} = require('react-relay');

const userFragment = graphql`
  fragment UserFragment_user on User {
    name
    age
    profile_picture(scale: 2) {
      uri
    }
  }
`;
```

## Rendering Fragments

In order to *render* the data for a fragment, you can use the `useFragment` Hook:

```js
import type {UserComponent_user$key} from 'UserComponent_user.graphql';

const React = require('React');

const {graphql, useFragment} = require('react-relay');

type Props = {
  user: UserComponent_user$key,
};

function UserComponent(props: Props) {
  const data = useFragment(
    graphql`
      fragment UserComponent_user on User {
        name
        profile_picture(scale: 2) {
          uri
        }
      }
    `,
    props.user,
  );

  return (
    <>
      <h1>{data.name}</h1>
      <div>
        <img src={data.profile_picture?.uri} />
      </div>
    </>
  );
}

module.exports = UserComponent;
```

Let's distill what's going on here:

* `useFragment` takes a fragment definition and a *fragment reference*, and returns the corresponding `data` for that fragment and reference.
  * This is similar to `usePreloadedQuery`, which takes a query definition and a query reference.
* A *fragment reference* is an object that Relay uses to *read* the data declared in the fragment definition; as you can see, the `UserComponent_user` fragment itself just declares fields on the `User` type, but we need to know *which* specific user to read those fields from; this is what the fragment reference corresponds to. In other words, a fragment reference is like *a pointer to a specific instance of a type* that we want to read data from.
* Note that *the component is automatically subscribed to updates to the fragment data*: if the data for this particular `User` is updated anywhere in the app (e.g. via fetching new data, or mutating existing data), the component will automatically re-render with the latest updated data.
* Relay will automatically generate Flow types for any declared fragments when the compiler is run, so you can use these types to declare the type for your Component's `props`.
    * The generated Flow types include a type for the fragment reference, which is the type with the `$key` suffix: `<fragment_name>$key`, and a type for the shape of the data, which is the type with the `$data` suffix:  `<fragment_name>$data`; these types are available to import from files that are generated with the following name: `<fragment_name>.graphql.js`.
    * We use our [lint rule](https://github.com/relayjs/eslint-plugin-relay) to enforce that the type of the fragment reference prop is correctly declared when using `useFragment`. By using a properly typed fragment reference as input, the type of the returned `data` will automatically be Flow-typed without requiring an explicit annotation.
    * In our example, we're typing the `user` prop as the fragment reference we need for `useFragment`, which corresponds to the `UserComponent_user$key` imported from  `UserComponent_user.graphql`, which means that the type of `data` above would be: `{ name: ?string, profile_picture: ?{ uri: ?string } }`.
* Fragment names need to be globally unique. A useful convention to help achieve this is to name fragments with a prefix followed by an identifier: e.g. `<ComponentName>_<property_name>`. This makes it easy to identify which fragments are defined in which components and avoids name collisions when multiple fragments are defined in the same module.


If you need to render data from multiple fragments inside the same component, you can use  `useFragment` multiple times:

```js
import type {UserComponent_user$key} from 'UserComponent_user.graphql';
import type {UserComponent_viewer$key} from 'UserComponent_viewer.graphql';

const React = require('React');
const {graphql, useFragment} = require('react-relay');

type Props = {
  user: UserComponent_user$key,
  viewer: UserComponent_viewer$key,
};

function UserComponent(props: Props) {
  const userData = useFragment(
    graphql`
      fragment UserComponent_user on User {
        name
        profile_picture(scale: 2) {
          uri
        }
      }
    `,
    props.user,
  );

  const viewerData = useFragment(
    graphql`
      fragment UserComponent_viewer on Viewer {
        actor {
          name
        }
      }
    `,
    props.viewer,
  );

  return (
    <>
      <h1>{userData.name}</h1>
      <div>
        <img src={userData.profile_picture?.uri} />
        Acting as: {viewerData.actor?.name ?? 'Unknown'}
      </div>
    </>
  );
}

module.exports = UserComponent;
```

## Composing Fragments

In GraphQL, fragments are reusable units, which means they can include *other* fragments, and consequently a fragment can be included within other fragments or [queries](../queries/):

```graphql
fragment UserFragment on User {
  name
  age
  profile_picture(scale: 2) {
    uri
  }
  ...AnotherUserFragment
}

fragment AnotherUserFragment on User {
  username
  ...FooUserFragment
}
```


With Relay, you can compose fragment components in a similar way, using both component composition and fragment composition. Each React component is responsible for fetching the data dependencies of its direct children - just as it has to know about its children's props in order to render them correctly. This pattern means that developers are able to reason locally about components - what data they need, what components they render - but Relay is able to derive a global view of the data dependencies of an entire UI tree.

```js
/**
 * UsernameSection.react.js
 *
 * Child Fragment Component
 */

import type {UsernameSection_user$key} from 'UsernameSection_user.graphql';

const React = require('React');
const {graphql, useFragment} = require('react-relay');

type Props = {
  user: UsernameSection_user$key,
};

function UsernameSection(props: Props) {
  const data = useFragment(
    graphql`
      fragment UsernameSection_user on User {
        username
      }
    `,
    props.user,
  );

  return <div>{data.username ?? 'Unknown'}</div>;
}

module.exports = UsernameSection;
```

```js
/**
 * UserComponent.react.js
 *
 * Parent Fragment Component
 */

import type {UserComponent_user$key} from 'UserComponent_user.graphql';

const React = require('React');
const {graphql, useFragment} = require('react-relay');

const UsernameSection = require('./UsernameSection.react');

type Props = {
  user: UserComponent_user$key,
};

function UserComponent(props: Props) {
  const user = useFragment(
    graphql`
      fragment UserComponent_user on User {
        name
        age
        profile_picture(scale: 2) {
          uri
        }

        # Include child fragment:
        ...UsernameSection_user
      }
    `,
    props.user,
  );

  return (
    <>
      <h1>{user.name}</h1>
      <div>
        <img src={user.profile_picture?.uri} />
        {user.age}

        {/* Render child component, passing the _fragment reference_: */}
        <UsernameSection user={user} />
      </div>
    </>
  );
}

module.exports = UserComponent;
```

There are a few things to note here:

* `UserComponent` both renders `UsernameSection`, *and* includes the fragment declared by `UsernameSection` inside its own `graphql` fragment declaration.
* `UsernameSection` expects a *fragment reference* as the `user` prop. As we've mentioned before, a fragment reference is an object that Relay uses to *read* the data declared in the fragment definition; as you can see, the child `UsernameSection_user` fragment itself just declares fields on the `User` type, but we need to know *which* specific user to read those fields from; this is what the fragment reference corresponds to. In other words, a fragment reference is like *a pointer to a specific instance of a type* that we want to read data from.
*  Note that in this case the `user` passed to `UsernameSection`, i.e. the fragment reference, *doesn't actually contain any of the data declared by the child `UsernameSection` component*; instead, `UsernameSection` will use the fragment reference to read the data *it* declared internally, using `useFragment`.
  * This means that the parent component will not receive the data selected by a child component (unless that parent explicitly selected the same fields). Likewise, child components will not receive the data selected by their parents (again, unless the child selected those same fields).
  * This prevents separate components from *even accidentally* having implicit dependencies on each other. If this wasn't the case, modifying a component could break other components!
  * This allows us to reason locally about our components and modify them without worrying about affecting other components.
  * This is known as [*data masking*](../../../principles-and-architecture/thinking-in-relay/).
* The *fragment reference* that the child (i.e.  `UsernameSection`) expects is the result of reading a parent fragment that *includes* the child fragment. In our particular example, that means the result of reading a fragment that includes `...UsernameSection_user` will be the fragment reference that `UsernameSection` expects. In other words, the data obtained as a result of reading a fragment via `useFragment` also serves as the fragment reference for any child fragments included in that fragment.


## Composing Fragments into Queries

Fragments in Relay allow declaring data dependencies for a component, but they ***can't be fetched by themselves***. Instead, they need to be included in a query, either directly or transitively. This means that *all fragments must belong to a query when they are rendered*, or in other words, they must be "rooted" under some query. Note that a single fragment can still be included by multiple queries, but when rendering a specific *instance* of a fragment component, it must have been included as part of a specific query request.

To fetch and render a query that includes a fragment, you can compose them in the same way fragments are composed, as shown in the [Composing Fragments](#composing-fragments) section:

```js
/**
 * UserComponent.react.js
 *
 * Fragment Component
 */

import type {UserComponent_user$key} from 'UserComponent_user.graphql';

const React = require('React');
const {graphql, useFragment} = require('react-relay');

type Props = {
  user: UserComponent_user$key,
};

function UserComponent(props: Props) {
  const data = useFragment(
    graphql`...`,
    props.user,
  );

  return (...);
}

module.exports = UserComponent;
```

```js
/**
 * App.react.js
 *
 * Query Component
 */

import type {AppQuery} from 'AppQuery.graphql';
import type {PreloadedQuery} from 'react-relay';

const React = require('React');
const {graphql, usePreloadedQuery} = require('react-relay');

const UserComponent = require('./UserComponent.react');

type Props = {
  appQueryRef: PreloadedQuery<AppQuery>,
}

function App({appQueryRef}) {
  const data = usePreloadedQuery(
    graphql`
      query AppQuery($id: ID!) {
        user(id: $id) {
          name

          # Include child fragment:
          ...UserComponent_user
        }
      }
    `,
    appQueryRef,
  );

  return (
    <>
      <h1>{data.user?.name}</h1>
      {/* Render child component, passing the fragment reference: */}
      <UserComponent user={data.user} />
    </>
  );
}
```

Note that:

* The *fragment reference* that  `UserComponent` expects is the result of reading a parent query that includes its fragment, which in our case means a query that includes `...UsernameSection_user`. In other words, the `data` obtained as a result of `usePreloadedQuery` also serves as the fragment reference for any child fragments included in that query.
* As mentioned previously, *all fragments must belong to a query when they are rendered,* which means that all fragment components *must* be descendants of a query. This guarantees that you will always be able to provide a fragment reference for `useFragment`, by starting from the result of reading a root query with `usePreloadedQuery`.

<DocsRating />

---

### Guided Tour Rendering Loading States (`website/docs/guided-tour/rendering/loading-states.mdx`)

---
id: loading-states
title: Loading States with Suspense
slug: /guided-tour/rendering/loading-states/
description: Relay guide to loading states
keywords:
- suspense
- loading
- glimmer
- fallback
- spinner
---

import DocsRating from '@site/src/core/DocsRating';
// @fb-only
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
// @fb-only
// @fb-only
// @fb-only
// @fb-only
// @fb-only


As you may have noticed, we mentioned that using `usePreloadedQuery` and `useLazyLoadQuery` will render data from a query that was being fetched from the server, but we didn't elaborate on how to render a loading UI (such as a glimmer) while that data is still being fetched. We will cover that in this section.

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

To render loading states while a query is being fetched, we rely on [React Suspense](https://reactjs.org/docs/concurrent-mode-suspense.html). Suspense is a new feature in React that allows components to interrupt or *"suspend"* rendering in order to wait for some asynchronous resource (such as code, images or data) to be loaded; when a component "suspends", it indicates to React that the component isn't *"ready"* to be rendered yet, and won't be until the asynchronous resource it's waiting for is loaded. When the resource finally loads, React will try to render the component again.

</OssOnly>

This capability is useful for components to express asynchronous dependencies like data, code, or images that they require in order to render, and lets React coordinate rendering the loading states across a component tree as these asynchronous resources become available. More generally, the use of Suspense give us better control to implement more deliberately designed loading states when our app is loading for the first time or when it's transitioning to different states, and helps prevent accidental flickering of loading elements (such as spinners), which can commonly occur when loading sequences aren't explicitly designed and coordinated.


<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

## Loading fallbacks with Suspense Boundaries

When a component is suspended, we need to render a *fallback* in place of the component while we wait for it to become *"ready"*. In order to do so, we use the `Suspense` component provided by React:

```js
const React = require('React');
const {Suspense} = require('React');

function App() {
  return (
    // Render a fallback using Suspense as a wrapper
    <Suspense fallback={<LoadingGlimmer />}>
      <CanSuspend />
    </Suspense>
  );
}
```


`Suspense` components can be used to wrap any component; if the target component suspends, `Suspense` will render the provided fallback until all its descendants become *"ready"* (i.e. until *all* of the suspended components within the subtree resolve). Usually, the fallback is used to render fallback loading states such as a glimmers and placeholders.

Usually, different pieces of content in our  app might suspend, so we can show loading state until they are resolved by using `Suspense` :

```js
/**
 * App.react.js
 */

const React = require('React');
const {Suspense} = require('React');

function App() {
  return (
    // LoadingGlimmer is rendered via the Suspense fallback
    <Suspense fallback={<LoadingGlimmer />}>
      <MainContent /> {/* MainContent may suspend */}
    </Suspense>
  );
}
```

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

Let's distill what's going on here:

* If `MainContent` suspends because it's waiting on some asynchronous resource (like data), the `Suspense` component that wraps `MainContent` will detect that it suspended, and will render the `fallback` element (i.e. the `LoadingGlimmer` in this case) up until `MainContent` is ready to be rendered. Note that this also transitively includes descendants of `MainContent`, which might also suspend.


What's nice about Suspense is that you have granular control about how to accumulate loading states for different parts of your component tree:

```js
/**
 * App.react.js
 */

const React = require('React');
const {Suspense} = require('React');

function App() {
  return (
    // A LoadingGlimmer for all content is rendered via the Suspense fallback
    <Suspense fallback={<LoadingGlimmer />}>
      <MainContent />
      <SecondaryContent /> {/* SecondaryContent can also suspend */}
    </Suspense>
  );
}
```

// @fb-only

* In this case, both `MainContent` and `SecondaryContent` may suspend while they load their asynchronous resources; by wrapping both in a `Suspense`, we can show a single loading state up until they are *all* ready, and then render the entire content in a single paint, after everything has successfully loaded.
* In fact, `MainContent` and `SecondaryContent` may suspend for different reasons other than fetching data, but the same `Suspense` component can be used to render a fallback up until *all* components in the subtree are ready to be rendered. Note that this also transitively includes descendants of `MainContent` or `SecondaryContent`, which might also suspend.


Conversely, you can also decide to be more granular about your loading UI and wrap Suspense components around smaller or individual parts of your component tree:

```js
/**
 * App.react.js
 */

const React = require('React');
const {Suspense} = require('React');

function App() {
  return (
    <>
      {/* Show a separate loading UI for the LeftHandColumn */}
      <Suspense fallback={<LeftColumnPlaceholder />}>
        <LeftColumn />
      </Suspense>

      {/* Show a separate loading UI for both the Main and Secondary content */}
      <Suspense fallback={<LoadingGlimmer />}>
        <MainContent />
        <SecondaryContent />
      </Suspense>
    </>
  );
}
```

// @fb-only

* In this case, we're showing 2 separate loading UIs:
    * One to be shown until the `LeftColumn` becomes ready
    * And one to be shown until both the `MainContent` and `SecondaryContent` become ready.
* What is powerful about this is that by more granularly wrapping our components in Suspense, *we allow other components to be rendered earlier as they become ready*. In our example, by separately wrapping `MainContent` and `SecondaryContent` under `Suspense`, we're allowing `LeftColumn` to render as soon as it becomes ready, which might be earlier than when the content sections become ready.


## Transitions and Updates that Suspend

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

`Suspense` boundary fallbacks allow us to describe our loading placeholders when initially rendering some content, but our applications will also have transitions between different content. Specifically, when switching between two components within an already mounted boundary, the new component you're switching to might not have loaded all of its async dependencies, which means that it might also suspend.

In these cases, we would still show the `Suspense` boundary fallbacks. However, this means that we would hide existing content in favor of showing the `Suspense` fallback. In future versions of React when concurrent rendering is supported, React will provide an option to support this case and avoid hiding already rendered content with a Suspense fallback when suspending.

</OssOnly>

## How We Use Suspense in Relay

### Queries

In our case, our query components are components that can suspend, so we use Suspense to render loading states while a query is being fetched. Let's see what that looks like in practice:

Say we have the following query renderer component:

```js
/**
 * MainContent.react.js
 *
 * Query Component
 */

const React = require('React');
const {graphql, usePreloadedQuery} = require('react-relay');

function MainContent(props) {
  // Fetch and render a query
  const data = usePreloadedQuery(
    graphql`...`,
    props.queryRef,
  );

  return (...);
}
```

```js
/**
 * App.react.js
 */

const React = require('React');
const {Suspense} = require('React');

function App() {
  return (
    // LoadingGlimmer is rendered via the Suspense fallback
    <Suspense fallback={<LoadingGlimmer />}>
      <MainContent /> {/* MainContent may suspend */}
    </Suspense>
  );
}
```

// @fb-only

Let's distill what's going on here:

* We have a `MainContent` component, which is a query renderer that fetches and renders a query. `MainContent` will *suspend* rendering when it attempts to fetch the query, indicating that it isn't ready to be rendered yet, and it will resolve when the query is fetched.
* The `Suspense `component that wraps `MainContent` will detect that `MainContent` suspended, and will render the `fallback` element (i.e. the `LoadingGlimmer` in this case) up until `MainContent` is ready to be rendered; that is, up until the query is fetched.


### Fragments

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

<OssOnly>

Fragments are also integrated with Suspense in order to support rendering of data that's being `@defer'`d or data that's partially available in the Relay Store (i.e. [partial rendering](../../reusing-cached-data/rendering-partially-cached-data/)).

</OssOnly>

### Transitions

<FbInternalOnly>
  // @fb-only
</FbInternalOnly>

Additionally, our APIs for fetching, [refreshing](../refetching/refreshing-queries.mdx) and [refetching](../refetching/refetching-queries-with-different-data.mdx) and for [rendering connections](../list-data/connections.mdx) are also integrated with Suspense; for these use cases, these APIs will also suspend.

<DocsRating />

---

### Guided Tour Rendering Queries (`website/docs/guided-tour/rendering/queries.mdx`)

---
id: queries
title: Queries
slug: /guided-tour/rendering/queries/
description: Relay guide to queries
keywords:
- query
- usePreloadedQuery
- useLazyLoadQuery
- useQueryLoader
- loadQuery
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

// @fb-only

A [GraphQL Query](https://graphql.org/learn/queries/) is a description of data you want to query from a GraphQL server. It consists of a set of fields (and potentially [fragments](../fragments/)) that we want to request from the GraphQL server. What we can query for will depend on the [GraphQL Schema](https://graphql.org/learn/schema/) exposed on the server, which describes the data that is available for querying.

A query can be sent as a request over the network, along with an optional collection of [variables](../variables/) that the query uses, in order to fetch the data. The server response will be a JSON object that matches the shape of the query we sent:

```graphql
query UserQuery($id: ID!) {
  user(id: $id) {
    id
    name
    ...UserFragment
  }
  viewer {
    actor {
      name
    }
  }
}

fragment UserFragment on User {
  username
}
```

<FbInternalOnly>

[Sample response](https://fburl.com/graphiql/v5hs717f):

</FbInternalOnly>

<OssOnly>

Sample response:

</OssOnly>

```json
{
  "data": {
    "user": {
      "id": "4",
      "name": "Mark Zuckerberg",
      "username": "zuck"
    },
    "viewer": {
      "actor": {
        "name": "Your Name"
      }
    }
  }
}
```



## Rendering Queries

To *render* a query in Relay, you can use the `usePreloadedQuery` hook. `usePreloadedQuery` takes a query definition and a query reference, and returns the corresponding data for that query and reference.

```js
import type {HomeTabQuery} from 'HomeTabQuery.graphql';
import type {PreloadedQuery} from 'react-relay';

const React = require('React');
const {graphql, usePreloadedQuery} = require('react-relay');

type Props = {
  queryRef: PreloadedQuery<HomeTabQuery>,
};

function HomeTab(props: Props) {
  const data = usePreloadedQuery(
    graphql`
      query HomeTabQuery($id: ID!) {
        user(id: $id) {
          name
        }
      }
    `,
    props.queryRef,
  );

  return (
    <h1>{data.user?.name}</h1>
  );
}
```

Lets see what's going on here:

* `usePreloadedQuery`  takes a `graphql` query and a `PreloadedQuery` reference, and returns the data that was fetched for that query.
    * The `PreloadedQuery` (in this case `queryRef`) is an object that describes and references an *instance* of our query that is being (or was) fetched.
        * We'll cover how to actually fetch the query in the next section below, and cover how to show loading states if the query is in-flight when we try to render it in the [Loading States with Suspense](../loading-states/) section.
* Similarly to [fragments](../fragments/), *the component is automatically subscribed to updates to the query data*: if the data for this query is updated anywhere in the app, the component will automatically re-render with the latest updated data.
* `usePreloadedQuery` also takes a Flow type parameter, which corresponds to the Flow type for the query, in this case `HomeTabQuery`.
    * The Relay compiler automatically generates Flow types for any declared queries, which are available to import from the generated files with the following name format: *`<query_name>`*`.graphql.js`.
    * Note that the `data` is already properly Flow-typed without requiring an explicit annotation, and is based on the types from the GraphQL schema. For example, the type of `data` above would be: `{ user: ?{ name: ?string } }`.
* Make sure you're providing a Relay environment using a [Relay Environment Provider](../environment/) at the root of your app before trying to render a query.


## Fetching Queries for Render

Apart from *rendering* a query, we also need to fetch it from the server. Usually we want to fetch queries somewhere at the root of our app, and only have **one or a few queries that [*accumulate*](../fragments/#composing-fragments-into-queries) all the data required to render the screen**. Ideally, we'd fetch them as early as possible, before we even start rendering our app.

In order to *fetch* a query for later rendering it, you can use the `useQueryLoader` Hook:

```js
import type {HomeTabQuery as HomeTabQueryType} from 'HomeTabQuery.graphql';
import type {PreloadedQuery} from 'react-relay';

const HomeTabQuery = require('HomeTabQuery.graphql')
const {useQueryLoader} = require('react-relay');


type Props = {
  initialQueryRef: PreloadedQuery<HomeTabQueryType>,
};

function AppTabs(props) {
  const [
    homeTabQueryRef,
    loadHomeTabQuery,
  ] = useQueryLoader(
    HomeTabQuery,
    props.initialQueryRef, /* e.g. provided by router */
  );

  const onSelectHomeTab = () => {
    // Start loading query for HomeTab immediately in the event handler
    // that triggers navigation to that tab, *before* we even start
    // rendering the target tab.
    // Calling this function will update the value of homeTabQueryRef.
    loadHomeTabQuery({id: '4'});

    // ...
  }

  // ...

  return (
    screen === 'HomeTab' && homeTabQueryRef != null ?
      // Pass to component that uses usePreloadedQuery
      <HomeTab queryRef={homeTabQueryRef} /> :
      // ...
  );
}
```

The example above is somewhat contrived, but let's distill what is happening:

* We are calling `useQueryLoader` inside our `AppTabs` component.
    * It takes a query, which in this case is our `HomeTabQuery` (the query that we declared in our previous example), and which we can obtain by requiring the auto-generated file: `'HomeTabQuery.graphql'`.
    * It takes an optional initial `PreloadedQuery` to be used as the initial value of the `homeTabQueryRef` that is stored in state and returned by `useQueryLoader`.
    * It also additionally takes a Flow type parameter, which corresponds to the Flow type for the query, in this case `HomeTabQueryType`, which you can also obtain from the auto-generated file: `'HomeTabQuery.graphql'`.
* Calling `useQueryLoader` allows us to obtain 2 things:
    * `homeTabQueryRef`: A `?PreloadedQuery`, which is an object that describes and references an *instance* of our query that is being (or was) fetched. This value will be null if we haven't fetched the query, i.e. if we haven't called `loadHomeTabQuery`.
    * `loadHomeTabQuery`: A function that will *fetch* the data for this query from the server (if it isn't already cached), and given an object with the [variables](../variables/) the query expects, in this case `{id: '4'}` (we'll go into more detail about how Relay uses cached data in the [Reusing Cached Data For Render](../../reusing-cached-data/) section). Calling this function will also update the value of `homeTabQueryRef` to an instance of a `PreloadedQuery`.
        * Note that the `variables` we pass to this function will be checked by Flow to ensure that you are passing values that match what the GraphQL query expects.
        * Also note that we are calling this function in the event handler that causes the `HomeTab` to be rendered. This allows us to start fetching the data for the screen as early as possible, even before the new tab starts rendering.
            * In fact, `loadQuery` will throw an error if it is called during React's render phase!
* Note that `useQueryLoader` will automatically dispose of all queries that have been loaded when the component unmounts. Disposing of a query means that Relay will no longer hold on to the data for that particular instance of the query in its cache (we'll cover the lifetime of query data in [Reusing Cached Data For Render](../../reusing-cached-data/) section). Additionally, if the request for the query is still in flight when disposal occurs, it will be canceled.
* Our `AppTabs` component renders the `HomeTab` component from the previous example, and passes it the corresponding query reference. Note that this parent component owns the lifetime of the data for that query, meaning that when it unmounts, it will of dispose of that query, as mentioned above.
* Finally, make sure you're providing a Relay environment using a [Relay Environment Provider](../environment/) at the root of your app before trying to use `useQueryLoader`.


Sometimes, you want to start a fetch outside of the context of a parent component, for example to fetch the data required for the initial load of the application. For these cases, you can use the `loadQuery` API directly, without using `useQueryLoader`:

```js
import type {HomeTabQuery as HomeTabQueryType} from 'HomeTabQuery.graphql';

const HomeTabQuery = require('HomeTabQuery.graphql')
const {loadQuery} = require('react-relay');


const environment = createEnvironment(...);

// At some point during app initialization
const initialQueryRef = loadQuery<HomeTabQueryType>(
  environment,
  HomeTabQuery,
  {id: '4'},
);

// ...

// E.g. passing the initialQueryRef to the root component
render(<AppTabs initialQueryRef={initialQueryRef} initialTab={...} />)
```

* In this example, we are calling the `loadQuery` function directly to obtain a `PreloadedQuery` instance that we can later pass to a component that uses `usePreloadedQuery`.
* In this case, we would expect the root `AppTabs` component to manage the lifetime of the query reference, and dispose of it at the appropriate time, if at all.
* We've left the details of "app initialization" vague in this example, since that will vary from application to application. The important thing to note here is that we should obtain a query reference before we start rendering the root component. In fact, `loadQuery` will throw an error if it is called during React's render phase!


### Render as you Fetch

The examples above illustrate how to separate fetching the data from rendering it, in order to start the fetch as early as possible (as opposed to waiting until the component is rendered to start the fetch), and allow us to show content to our users a lot sooner. It also helps prevent waterfalling round trips, and gives us more control and predictability over when the fetch occurs, whereas if we fetch during render, it becomes harder to determine when the fetch will (or should) occur. This fits nicely with the [*"render-as-you-fetch"*](https://reactjs.org/docs/concurrent-mode-suspense.html#approach-3-render-as-you-fetch-using-suspense) pattern with [React Suspense](../loading-states/).

This is the preferred pattern for fetching data with Relay, and it applies in several circumstances, such as the initial load of an application, during subsequent navigations, or generally when using UI elements which are initially hidden and later revealed upon an interaction (such as menus, popovers, dialogs, etc), and which also require fetching additional data.

// @fb-only


## Lazily Fetching Queries during Render

Another alternative for fetching a query is to lazily fetch the query when the component is rendered. However, as we've mentioned previously, the preferred pattern is to start fetching queries ahead of rendering. If lazy fetching is used without caution, it can trigger nested or waterfalling round trips, and can degrade performance.

To fetch a query lazily, you can use the `useLazyLoadQuery` Hook:

```js
const React = require('React');
const {graphql, useLazyLoadQuery} = require('react-relay');

function App() {
  const data = useLazyLoadQuery(
    graphql`
      query AppQuery($id: ID!) {
        user(id: $id) {
          name
        }
      }
    `,
    {id: '4'},
  );

  return (
    <h1>{data.user?.name}</h1>
  );
}
```
Lets see what's going on here:

* `useLazyLoadQuery`  takes a graphql query and some variables for that query, and returns the data that was fetched for that query. The variables are an object containing the values for the [variables](../variables/) referenced inside the GraphQL query.
* Similarly to [fragments](../fragments/), the component is automatically subscribed to updates to the query data: if the data for this query is updated anywhere in the app, the component will automatically re-render with the latest updated data.
* `useLazyLoadQuery` additionally takes a Flow type parameter, which corresponds to the Flow type for the query, in this case AppQuery.
    * Remember that Relay automatically generates Flow types for any declared queries, which you can import and use with `useLazyLoadQuery`. These types are available in the generated files with the following name format: `<query_name>.graphql.js`.
    * Note that the `variables` will be checked by Flow to ensure that you are passing values that match what the GraphQL query expects.
    * Note that the data is already properly Flow-typed without requiring an explicit annotation, and is based on the types from the GraphQL schema. For example, the type of `data` above would be: `{ user: ?{ name: ?string } }`.
* By default, when the component renders, Relay will *fetch* the data for this query (if it isn't already cached), and return it as a the result of the `useLazyLoadQuery` call. We'll go into more detail about how to show loading states in the [Loading States with Suspense](../loading-states/) section, and how Relay uses cached data in the [Reusing Cached Data For Rendering](../../reusing-cached-data/) section.
* Note that if you re-render your component and pass *different query variables* than the ones originally used, it will cause the query to be fetched again with the new variables, and potentially re-render with different data.
* Finally, make sure you're providing a Relay environment using a [Relay Environment Provider](../../../api-reference/relay-environment-provider/) at the root of your app before trying to render a query.


<DocsRating />

---

### Guided Tour Rendering Variables (`website/docs/guided-tour/rendering/variables.mdx`)

---
id: variables
title: Variables
slug: /guided-tour/rendering/variables/
description: Relay guide to query variables
keywords:
- query
- variables
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

You may have noticed that the query declarations in our examples above contain references to an `$id` symbol inside the GraphQL code: these are [GraphQL Variables](https://graphql.org/learn/queries/#variables).

GraphQL variables are a construct that allows referencing dynamic values inside a GraphQL query. When fetching a query from the server, we also need to provide as input the actual set of values to use for the variables declared inside the query:

```graphql
query UserQuery($id: ID!) {
  # The value of $id is used as input to the user() call:
  user(id: $id) {
    id
    name
  }
}
```

In the above, `ID!` is the type of the `$id` variable. That is, it is a required ID.

When sending a network request to fetch the query above, we need to provide both the query, and the variables to be used for this particular execution of the query.  For example:

```graphql
# Query:
query UserQuery($id: ID!) {
  # ...
}

# Variables:
{"id": 4}
```


<FbInternalOnly>

Fetching the above query and variables from the server would produce the following response, which can also be visualized in [GraphiQL](https://fburl.com/graphiql/kiuar058):

</FbInternalOnly>

<OssOnly>

Fetching the above query and variables from the server would produce the following response:

</OssOnly>

```json
{
  "data": {
    "user": {
      "id": "4",
      "name": "Mark Zuckerberg"
    }
  }
}
```


* * *

Fragments can also reference variables that have been declared by a query:

```graphql
fragment UserFragment on User {
  name
  profile_picture(scale: $scale) {
    uri
  }
}


query ViewerQuery($scale: Float!) {
  viewer {
    actor {
      ...UserFragment
    }
  }
}
```

* Even though the fragment above doesn't *declare* the `$scale` variable directly, it can still reference it. Doing so makes it so any query that includes this fragment, either directly or transitively, *must* declare the variable and its type, otherwise an error will be produced.
* In other words, *query variables are available globally by any fragment that is a descendant of the query*.
* A fragment which references a global variable can only be included (directly or transitively) in a query which defines that global variable.


In Relay, fragment declarations inside components can also reference query variables:

```js
function UserComponent(props: Props) {
  const data = useFragment(
    graphql`
    fragment UserComponent_user on User {
      name
      profile_picture(scale: $scale) {
        uri
      }
    }
    `,
    props.user,
  );

  return (...);
}
```

* The above fragment could be included by multiple queries, and rendered by different components, which means that any query that ends up rendering/including the above fragment *must* declare the `$scale` variable.
*  If any query that happens to include this fragment *doesn't* declare the `$scale` variable, an error will be produced by the Relay Compiler at build time, ensuring that an incorrect query never gets sent to the server (sending a query with missing variable declarations will also produce an error in the server).



## @arguments and @argumentDefinitions

Relay also provides a way to declare variables that are scoped locally to a fragment using the `@arguments` and `@argumentDefinitions` directives. Fragments that use local variables are easy to customize and reuse, since they do not depend on the value of global (query-level) variables.

```js
/**
 * Declare a fragment that accepts arguments with @argumentDefinitions
 */

function TaskView(props) {
  const data = useFragment(
    graphql`
      fragment TaskView_task on Task
        @argumentDefinitions(showDetailedResults: {type: "Boolean!"}) {
        name
        is_completed
        ... @include(if: $showDetailedResults) {
          description
        }
      }
    `,
    props.task,
  );
}
```

```js
/**
 * Include fragment using @arguments
 */

function TaskList(props) {
  const data = usePreloadedQuery(
    graphql`
      query TaskListQuery {
        todays_tasks {
          ...TaskView_task @arguments(showDetailedResults: true)
        }
        tomorrows_tasks {
          ...TaskView_task @arguments(showDetailedResults: false)
        }
      }
    `,
    props.queryRef,
  );
}
```

* Locally-scoped variables also make it easier to reuse a fragment from another query.
  * A query definition must list all variables that are used by any nested fragments, including in recursively-nested fragments.
  * Since a fragment can potentially be accessible from many queries, modifying a fragment that uses global variables can require changes to many query definitions.
  * This can also lead to awkward situations, like having multiple versions of the "same" variable, such as `$showDetailedResults` and `$showDetails`.

  * Since fragments with only locally-scoped variables do not use global variables, they do not suffer from this issue.

* Note that when passing `@arguments` to a fragment, we can pass a literal value or pass another variable. The variable can be a global query variable, a local variable declared via `@argumentDefinitions` or a literal (e.g. `42.0`).
* When we actually fetch `TaskView_task` as part of a query, the `showDetailedResults` value will depend on the argument that was provided by the parent of `TaskView_task`:

Fragments that expect arguments can also declare default values, making the arguments optional:

```js
/**
 * Declare a fragment that accepts arguments with default values
 */

function TaskView(props) {
  const data = useFragment(
    graphql`
      fragment TaskView_task on Task
        @argumentDefinitions(showDetailedResults: {type: "Boolean!", defaultValue: true}) {
        name
        is_completed
        ... @include(if: $showDetailedResults) {
          description
        }
      }
    `,
    props.task,
  );
}
```

```js
function TaskList(props) {
  const data = usePreloadedQuery(
    graphql`
      query TaskListQuery {
        todays_tasks {
          ...TaskView_task
        }
        tomorrows_tasks {
          ...TaskView_task @arguments(showDetailedResults: false)
        }
      }
    `,
    props.queryRef,
  );
}
```

* Not passing the argument to `TaskView_task` makes it use the default value for its locally declared `$showDetailedResult` variable.



## Accessing GraphQL Variables At Runtime


If you want to access the variables that were set at the query root, the recommended approach is to pass the variables down the component tree in your application, using props, or your own application-specific context.

Relay currently does not expose the resolved variables (i.e. after applying argument definitions) for a specific fragment, and you should very rarely need to do so.




<DocsRating />

---

### Guided Tour Reusing Cached Data Fetch Policies (`website/docs/guided-tour/reusing-cached-data/fetch-policies.mdx`)

---
id: fetch-policies
title: Fetch Policies
slug: /guided-tour/reusing-cached-data/fetch-policies/
description: Relay guide to fetch policies
keywords:
- fetch policy
- network-only
- store-only
- store-and-network
- store-or-network
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

The first step to reusing locally cached data is to pass a `fetchPolicy` to the `loadQuery` function, which can be provided by `useQueryLoader` (see the [Fetching Queries section](../../rendering/queries/)):

```js
const React = require('React');
const {graphql} = require('react-relay');

function AppTabs() {
  const [
    queryRef,
    loadQuery,
  ] = useQueryLoader(HomeTabQuery);

  const onSelectHomeTab = () => {
    loadQuery({id: '4'}, {fetchPolicy: 'store-or-network'});
  }

  // ...
}
```

The provided `fetchPolicy` will determine:

* *whether* the query should be fulfilled from the local cache, and
* *whether* a network request should be made to fetch the query from the server, depending on the availability of the data for that query in the store.


By default, Relay will try to read the query from the local cache; if any piece of data for that query is [missing](../presence-of-data/) or [stale](../staleness-of-data/), it will fetch the entire query from the network. This default `fetchPolicy` is called "*store-or-network".*

Specifically, `fetchPolicy` can be any of the following options: **

* "store-or-network": *(default)* *will* reuse locally cached data, and will *only* send a network request if any data for the query is [missing](../presence-of-data/) or [stale](../staleness-of-data/). If the query is fully cached, a network request will *not* be made.
* "store-and-network": *will* reuse locally cached data and will *always* send a network request, regardless of whether any data was [missing](../presence-of-data/) or [stale](../staleness-of-data/) in the store.
* "network-only": *will* *not* reuse locally cached data, and will *always* send a network request to fetch the query, ignoring any data that might be locally cached and whether it's [missing](../presence-of-data/) or [stale](../staleness-of-data/).
* "store-only": *will* *only* reuse locally cached data, and will *never* send a network request to fetch the query. In this case, the responsibility of fetching the query falls to the caller, but this policy could also be used to read and operate on data that is entirely [local](../../updating-data/local-data-updates/).


Note that the `refetch` function discussed in the [Refetching Queries](../refetching/refetching-queries-with-different-data.mdx) section also takes a `fetchPolicy`.


<DocsRating />

---

### Guided Tour Reusing Cached Data Filling In Missing Data (`website/docs/guided-tour/reusing-cached-data/filling-in-missing-data.mdx`)

---
id: filling-in-missing-data
title: Filling in Missing Data (Missing Field Handlers)
slug: /guided-tour/reusing-cached-data/filling-in-missing-data/
description: Relay guide to filling in missing data
keywords:
- missing field handler
- missing data
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

// @fb-only

In the previous section we covered how to reuse data that is fully or partially cached, however there are cases in which Relay can't automatically tell that it can reuse some of the data it already has from other queries in order to fulfill a specific query. Specifically, Relay knows how to reuse data that is cached for a query that has been fetched before; that is, if you fetch the exact same query twice, Relay will know that it has the data cached for that query the second time it tries to evaluate it.

However, when using different queries, there might still be cases where different queries point to the same data, which we'd want to be able to reuse. For example, imagine the following two queries:

```js
// Query 1

query UserQuery {
  user(id: 4) {
    name
  }
}
```

```js
// Query 2

query NodeQuery {
  node(id: 4) {
    ... on User {
      name
    }
  }
}
```


These two queries are different, but reference the exact same data. Ideally, if one of the queries was already cached in the store, we should be able to reuse that data when rendering the other query. However, Relay doesn't have this knowledge by default, so we need to configure it to encode the knowledge that a `node(id: 4)` *"is the same as"* `user(id: 4)`.

To do so, we can provide `missingFieldHandlers` to the `RelayEnvironment` which specifies this knowledge.

// @fb-only

```js
const {ROOT_TYPE, Environment} = require('relay-runtime');

const missingFieldHandlers = [
  {
    handle(field, record, argValues): ?string {
      // Make sure to add a handler for the node field
      if (
        record != null &&
        record.getType() === ROOT_TYPE &&
        field.name === 'node' &&
        argValues.hasOwnProperty('id')
      ) {
        return argValues.id
      }
      if (
        record != null &&
        record.getType() === ROOT_TYPE &&
        field.name === 'user' &&
        argValues.hasOwnProperty('id')
      ) {
        // If field is user(id: $id), look up the record by the value of $id
        return argValues.id;
      }
      if (
        record != null &&
        record.getType() === ROOT_TYPE &&
        field.name === 'story' &&
        argValues.hasOwnProperty('story_id')
      ) {
        // If field is story(story_id: $story_id), look up the record by the
        // value of $story_id.
        return argValues.story_id;
      }
      return undefined;
    },
    kind: 'linked',
  },
];

const environment = new Environment({/*...*/, missingFieldHandlers});
```

* `missingFieldHandlers` is an array of *handlers*. Each handler must specify a `handle` function, and the kind of missing fields it knows how to handle. The 2 main types of fields that you'd want to handle are:
    * *'scalar'*: This represents a field that contains a scalar value, for example a number or a string.
    * *'linked'*: This represents a field that references another object, i.e. not a scalar.
* The `handle` function takes the field that is missing, the record that field belongs to, and any arguments that were passed to the field in the current execution of the query.
    * When handling a *'scalar'* field, the handle function should return a scalar value, in order to use as the value for a missing field
    * When handling a *'linked'* field*,* the handle function should return an *ID*, referencing another object in the store that should be use in place of the missing field. **
* As Relay attempts to fulfill a query from the local cache, whenever it detects any missing data, it will run any of the provided missing field handlers that match the field type before definitively declaring that the data is missing.



<DocsRating />

---

### Guided Tour Reusing Cached Data Introduction (`website/docs/guided-tour/reusing-cached-data/introduction.mdx`)

---
id: introduction
title: Reusing Cached Data
slug: /guided-tour/reusing-cached-data/
description: Relay guide to reusing cached data
keywords:
- reusing
- cached
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';

While an app is in use, Relay will accumulate and cache *(for some time)* the data for the multiple queries that have been fetched throughout usage of our app. Often times, we'll want to be able to reuse and immediately render this data that is locally cached instead of waiting for a network request when fulfilling a query; this is what we'll cover in this section.

Some examples of when this might be useful are:

* Navigating between tabs in an app, where each app renders a query. If a tab has already been visited, re-visiting the tab should render it instantly, without having to wait for a network request to fetch the data that we've already fetched before.
* Navigating to a post that was previously rendered on a feed. If the post has already been rendered on a feed, navigating to the post's permalink page should render the post immediately, since all of the data for the post should already be cached.
    * Even if rendering the post in the permalink page requires more data than rendering the post on a feed, we'd still like to reuse and immediately render as much of the post's data that we already have available locally, without blocking render for the entire post if only a small bit of data is missing.

<DocsRating />

---

### Guided Tour Reusing Cached Data Presence Of Data (`website/docs/guided-tour/reusing-cached-data/presence-of-data.mdx`)

---
id: presence-of-data
title: Presence of Data
slug: /guided-tour/reusing-cached-data/presence-of-data/
description: Relay guide to the presence of data
keywords:
- presence
---

import DocsRating from '@site/src/core/DocsRating';
import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
// @fb-only


An important thing to keep in mind when attempting to reuse data that is cached in the Relay store is to understand the lifetime of that data; that is, if it is present in the store, and for how long it will be.

Data in the Relay store for a given query will generally be present after the query has been fetched for the first time, as long as that query is being rendered on the screen. If we've never fetched data for a specific query, then it will be missing from the store.

However, even after we've fetched data for different queries, we can't keep all of the data that we've fetched indefinitely in memory, since over time it would grow to be too large and too stale. In order to mitigate this, Relay runs a process called *Garbage Collection*, in order to delete data that we're no longer using.

## Garbage Collection in Relay

Specifically, Relay runs garbage collection on the local in-memory store by deleting any data that is no longer being referenced by any component in the app.

However, this can be at odds with reusing cached data; if the data is deleted too soon, before we try to reuse it again later, that will prevent us from reusing that data to render a screen without having to wait on a network request. To address this, this section will cover what you need to do in order to ensure that the data you want to reuse is kept cached for as long as you need it.


:::note
NOTE: Usually, you shouldn't need to worry about configuring garbage collection and data retention, as this should be configured by the app infrastructure at the RelayEnvironment level; however, we will cover it here for reference.
:::

// @fb-only



## Query Retention

Retaining a query indicates to Relay that the data for that query and variables shouldn't be deleted (i.e. garbage collected). Multiple callers might retain a single query, and as long as there is at least one caller retaining a query, it won't be deleted from the store.

By default, any query components using `useQueryLoader` / `usePreloadedQuery` or our other APIs will retain the query for as long as they are mounted. After they unmount, they will release the query, which means that the query might be deleted at any point in the future after that occurs.

If you need to retain a specific query outside of the components lifecycle, you can use the [`retain`](../../accessing-data-without-react/retaining-queries/) operation:

```js
// Retain query; this will prevent the data for this query and
// variables from being garbage collected by Relay
const disposable = environment.retain(queryDescriptor);

// Disposing of the disposable will release the data for this query
// and variables, meaning that it can be deleted at any moment
// by Relay's garbage collection if it hasn't been retained elsewhere
disposable.dispose();
```

* As mentioned, this will allow you to retain the query even after a query component has unmounted, allowing other components, or future instances of the same component, to reuse the retained data.


## Controlling Relay's Garbage Collection Policy

There are currently 2 options you can provide to your Relay Store in to control the behavior of garbage collection:

### GC Scheduler

The `gcScheduler` is a function you can provide to the Relay Store which will determine when a GC execution should be scheduled to run:

```js
// Sample scheduler function
// Accepts a callback and schedules it to run at some future time.
function gcScheduler(run: () => void) {
  resolveImmediate(run);
}

const store = new Store(source, {gcScheduler});
```

* By default, if a `gcScheduler` option is not provided, Relay will schedule garbage collection using the `resolveImmediate` function.
* You can provide a scheduler function to make GC scheduling less aggressive than the default, for example based on time or [scheduler](https://github.com/facebook/react/tree/main/packages/scheduler) priorities, or any other heuristic. By convention, implementations should not execute the callback immediately.


### GC Release Buffer Size

The Relay Store internally holds a release buffer to keep a specific (configurable) number of queries temporarily retained even *after* they have been released by their original owner  (which will happen by default when a component rendering that query unmounts). This makes it possible (and more likely) to be able to reuse data when navigating back to a page, tab or piece of content that has been visited before.

In order to configure the size of the release buffer, we can specify the `gcReleaseBufferSize` option to the Relay Store:

```js
const store = new Store(source, {gcReleaseBufferSize: 10});
```

* Note that having a buffer size of 0 is equivalent to not having the release buffer, which means that queries will be immediately released and collected.
* By default, environments have a release buffer size of 10.

<DocsRating />

---

--- METRICS ---
- Files Extracted: 100
- Estimated Token Budget: ~163837 tokens
- Canonical Reference: https://codewiki.google/github.com/facebook/relay
