17 hands-on exercises · runs 100% in your browser

Learn Relay
by solving problems.

The Relay workshop by Sibelius Seraphini, rebuilt as an interactive playground. Write real Relay code, watch the store update, and pass the checks, all without installing anything.

Post.tsx
import { graphql, useFragment } from 'react-relay';

const Post = (props) => {
  const post = useFragment(
    graphql`
      fragment Post_post on Post {
        content
        author { name }
      }
    `,
    props.post,
  );

  return <Text>{post.content}</Text>;
};

The real Relay compiler

Your graphql tags are compiled by the official Rust Relay compiler, running as WebAssembly in your browser.

A GraphQL server in a tab

A mini social network with posts, comments, likes, auth and subscriptions. No setup, no MongoDB.

See inside Relay

Inspect every request in the Network tab and watch normalized records change in the Relay Store tab.

Instant feedback

Automated checks run against your app, so you know when you solved it. Stuck? Hints and solutions are one click away.

Exercises

Start from the beginning, or jump to the topic you want to learn. Your progress is saved in this browser.

0/17 solved
01

Fetch GraphQL

Fetch GraphQL data with plain React: fetch, useState and useEffect. No Relay yet.

fetchuseEffect
02

useLazyLoadQuery

Fetch your first Relay query with useLazyLoadQuery, Suspense and an ErrorBoundary.

useLazyLoadQueryEnvironmentSuspense
03

useFragment

Colocate data requirements: each component declares its own fragment with useFragment.

useFragmentdata masking
04

usePaginationFragment

Paginate a list of posts using connections, @refetchable and usePaginationFragment.

usePaginationFragment@connection@refetchable@argumentDefinitions
05

useMutation

Like a post: authenticate the network layer and modify data with useMutation and optimistic responses.

useMutationoptimisticResponsenetwork layer
06

Mutation updater

Insert a new comment into a connection with an updater, no refetch needed.

updaterConnectionHandleroptimisticUpdaterRelay store
07

useRefetchableFragment

Refetch a fragment with new variables using useRefetchableFragment and useTransition.

useRefetchableFragment@refetchableuseTransition
08

useSubscription

Listen to new posts in realtime with useSubscription and update the feed connection.

useSubscriptionupdaterconnections
09

usePreloadedQuery

Render-as-you-fetch: start loading data in the router with loadQuery and read it with usePreloadedQuery.

usePreloadedQueryloadQueryreact-router
10testing

test usePreloadedQuery

Test a route component that uses usePreloadedQuery with createMockEnvironment and MockPayloadGenerator.

relay-test-utilscreateMockEnvironmentMockPayloadGeneratortesting-library
11testing

test useFragment

Test a fragment component (PostLikeButton) using a @relay_test_operation wrapper query.

@relay_test_operationrelay-test-utilsMockPayloadGeneratortesting-library
12testing

test useMutation

Click the like button, assert the PostLikeMutation variables and mock the mutation response.

relay-test-utilsgetMostRecentOperationresolveMostRecentOperationfireEvent
13

Declarative directives

Add the created post to the feed connection with @prependEdge/@appendEdge, no updater needed.

@prependEdge@appendEdge@deleteEdgeconnections
14bonus

Optimistic updates

Make mutations feel instant with optimisticResponse and optimisticUpdater, and see them rolled back.

optimisticResponseoptimisticUpdateruseMutation
15bonus

Fetch policies & refreshing

Decide when to read from the store or the network with fetchPolicy, and refresh a query with fetchKey.

fetchPolicyfetchKeyuseTransition
16bonus

The Relay store: local updates

Read and write the Relay store directly with commitLocalUpdate, ConnectionHandler and getStore().

commitLocalUpdateConnectionHandlerRecordSource
17bonus

@required & error boundaries

Handle nullable fields declaratively with @required(action: LOG | THROW) and recover with an error boundary.

@requiredErrorBoundarynullability