Relay is built upon locally declaring data dependencies for components. This means each component declares what data that it needs, without worrying about how to fetch it; Relay guarantees that the data each component needs is fetched and available.
This allows components and their data dependencies to be modified quickly and in isolation, without needing to update other parts of the system or, worrying about breaking other components
Relay automatically aggregates the data requirements for your entire application, so that they can be fetched in a single GraphQL request.
Relay will handle all of the heavy lifting to ensure the data declared by your components is fetched in the most efficient way, for example by deduplicating identical fields, fetching as early as possible, among other optimizations.
Relay automatically keeps all of your components up to date whenever data that affects them changes, and efficiently update them only when strictly necessary.
Relay also supports executing GraphQL Mutations, optionally with optimistic updates, and updates to local data, while ensuring that visible data on the screen is always kept up to date.
When creating a new screen, you start with a QueryRenderer
.
A QueryRenderer
is a React Component which is the root of a Relay component tree. It handles fetching your query, and uses the render
prop to render the resulting data.
As React components, QueryRenderers
can be rendered anywhere that a React component can be rendered, i.e. not just at the top level but *within* other components or containers. For example, you could use a QueryRenderer
to lazily fetch additional data for a popover.
import React from "react" import { createFragmentContainer, graphql, QueryRenderer } from "react-relay" import environment from "./lib/createRelayEnvironment" import ArtistHeader from "./ArtistHeader" // Below you can usually use one query renderer per page // and it represents the root of a query export default function ArtistRenderer({artistID}) { return ( <QueryRenderer environment={environment} query={graphql` query QueryRenderersArtistQuery($artistID: String!) { # The root field for the query artist(id: $artistID) { # A reference to your fragment container ...ArtistHeader_artist } } `} variables={{artistID}} render={({error, props}) => { if (error) { return <div>{error.message}</div>; } else if (props) { return <ArtistHeader artist={props.artist} />; } return <div>Loading</div>; }} /> ); }
Step two is to render a tree of React components powered by Relay, which may include FragmentContainers
, PaginationContainers
, or RefetchContainers
.
The most common are FragmentContainers
, which you can use to declare a specification of the data that a Component will need in order to render. Note that a FragmentContainer
won't directly fetch the data; instead, the data will be fetched by a QueryRenderer ancestor at the root, which will aggregate all of the data needed for a tree of Relay components, and fetch it in a *single round trip*.
Relay will then guarantee that the data declared by aFragmentContainer
is available *before* rendering the component.
import React from "react" import { createFragmentContainer, graphql } from "react-relay" import { Link, Image, Name, Bio, View,} from "./views" function ArtistHeader(props) { const {name, href, image, bio} = props.artist; const imageUrl = image && image.url; return ( <Link href={href}> <Image imageUrl={imageUrl} /> <View> <Name>{name}</Name> <Bio>{bio}</Bio> </View> </Link> ); } export default createFragmentContainer(ArtistHeader, { artist: graphql` # This fragment is declaring that this component # needs an Artist, and these specific fields on # the Artist in order to render. Relay will # guarantee that this data is fetched and available # for this component. fragment ArtistHeader_artist on Artist { href bio name image { url } } `, });
A GraphQL Fragment is a reusable selection of fields for a given GraphQL type. It can be composed by including it in other Fragments, or including it as part of GraphQL Queries.
Relay uses Fragments to declare data requirements for components, and compose data requirements together.
See the Fragment Container docs
GraphQL Connections are a model for representing lists of data in GraphQL, so that they can easily be paginated in any direction, as well as to be able to encode rich relationship data.
GraphQL Connections are considered a best practice for Pagination in GraphQL, and Relay provides first class support for these, as long as your GraphQL server supports them.
See the Connections docs
Relay relies on Global Object Identification to provide reliable caching and refetching, and to make it possible to automatically merge updates for objects.
Global Object Identification consists on providing globally unique ids across your entire schema for every type, built using the Node GraphQL interface.
Using GraphQL mutations, you can declaratively define and request the data that will be affected by executing a mutation in a single round trip, and Relay will automatically merge and propagate those changes.
Using Global Object Identification, Relay is capable of automatically merging mutation updates for any affected objects, and updating only the affected components.
For more complex cases where updates cannot automatically be merged, Relay provides apis to manually update the local Relay data in response to a mutation.
Relay's mutation API supports making optimistic updates to show immediate feedback to users, as well as error handling and automatically reverting changes when mutations fail.
While you work on a Relay project, the Relay compiler will guide you to ensure project-wide consistency and correctness against your GraphQL schema.
Relay pre-computes a lot of work (like processing and optimizing queries) ahead of time, during build time, in order to make the runtime on the browser or device as efficient as possible.
Relay generates Flow or TypeScript types for each of your React components that use Relay, which represent the data that each component receives, so you can make changes more quickly and safely while knowing that correctness is guaranteed.
If you already can render React components, you’re most of the way there. Relay requires a Babel plugin, and to also run the Relay Compiler.
You can use Relay out of the box with Create React App and Next.js.
Relay requires a bit more up-front setup and tools, in favour of supporting an architecture of isolated components which can scale with your team and app complexity.
Learn these principles once, then spend more time working on business logic instead of pipelining data.
Relay is critical infrastructure in Facebook, there are tens of thousands of components using it. Relay was built in tandem with GraphQL and has full-time staff working to improve it.
If you’re the sort of team that believes in using Flow or TypeScript to move error detection to dev-time, then Relay is likely a good fit for you.
It’s probable you’d otherwise re-create a lot of Relay’s caching, and UI best practices independently.
Used on 1stdibs.com
Used on artsy.net, and the React Native iOS app, Eigen.
Powers feedback.house
Used on facebook.com, and in the React Native mobile app.
Used on oculus.com, Oculus Home in VR, and the React Native Oculus companion app.
Used at autoguru.com.au, and affiliates