### Clone and Run Relay Example Project
Source: https://relay.dev/docs/tutorial/intro
Clone the example project and install dependencies to start the development server. Ensure git and npm are installed.
```bash
git clone https://github.com/relayjs/relay-examples.git
cd relay-examples/newsfeed
npm install
npm run dev
```
--------------------------------
### Basic useLazyLoadQuery Example
Source: https://relay.dev/docs/api-reference/use-lazy-load-query
This example demonstrates the basic usage of `useLazyLoadQuery` to fetch user data. It specifies the GraphQL query, variables, and a fetch policy. The hook returns data that matches the query shape.
```javascript
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
{data.user?.name} ;
}
```
--------------------------------
### Install Relay Babel Plugin
Source: https://relay.dev/docs/getting-started/babel-plugin
Install the babel-plugin-relay and graphql packages as development dependencies using yarn.
```bash
yarn add --dev babel-plugin-relay graphql
```
--------------------------------
### Install Relay Dependencies
Source: https://relay.dev/docs/getting-started/quick-start
Install necessary runtime and development dependencies for Relay, including the compiler and Babel plugin.
```bash
cd relay-example
# Runtime dependencies
npm install relay-runtime react-relay
# Dev dependencies
npm install --save-dev babel-plugin-relay graphql relay-compiler
# Types
npm install --save-dev @types/relay-runtime @types/react-relay
```
--------------------------------
### Basic commitMutation Example
Source: https://relay.dev/docs/api-reference/commit-mutation
This example demonstrates how to use `commitMutation` to like a feedback item. It includes the mutation definition, variables, and the necessary imports. The `Disposable` returned can be used to cancel the operation.
```javascript
import type {FeedbackLikeMutation} from 'FeedbackLikeMutation.graphql';
const React = require('React');
const {graphql, commitMutation} = require('react-relay');
function likeFeedback(environment: IEnvironment): Disposable {
return commitMutation(environment, {
mutation: graphql`
mutation FeedbackLikeMutation($input: FeedbackLikeData!) {
feedback_like(data: $input) {
feedback {
id
viewer_does_like
like_count
}
}
}
`,
variables: {
input: {
id: '123',
},
},
});
}
```
--------------------------------
### Install Relay ESLint Plugin
Source: https://relay.dev/docs/getting-started/lint-rules
Install the `eslint-plugin-relay` package as a development dependency using npm.
```bash
npm install --save-dev eslint-plugin-relay
```
--------------------------------
### Subscription Payload Example
Source: https://relay.dev/docs/guided-tour/updating-data/graphql-subscriptions
An example of a subscription payload that a client might receive in response to a server-side event.
```json
{
"feedback_like_subscribe": {
"feedback": {
"id": "feedback-id",
"like_count": 321,
}
}
}
```
--------------------------------
### GraphQL Fragment Composition Example
Source: https://relay.dev/docs/guided-tour/rendering/fragments
Demonstrates how GraphQL fragments can include other fragments, creating reusable data fetching units.
```graphql
fragment UserFragment on User {
name
age
profile_picture(scale: 2) {
uri
}
...AnotherUserFragment
}
fragment AnotherUserFragment on User {
username
...FooUserFragment
}
```
--------------------------------
### useMutation Hook Example
Source: https://relay.dev/docs/api-reference/use-mutation
This example demonstrates how to use the `useMutation` hook to commit a GraphQL mutation. It includes handling the loading state and defining the mutation with its variables and completion callback.
```javascript
import type {FeedbackLikeMutation} from 'FeedbackLikeMutation.graphql';
const React = require('React');
const {graphql, useMutation} = require('react-relay');
function LikeButton() {
const [commit, isInFlight] = useMutation(graphql`
mutation FeedbackLikeMutation($input: FeedbackLikeData!) {
feedback_like(data: $input) {
feedback {
id
viewer_does_like
like_count
}
}
}
`);
if (isInFlight) {
return ;
}
return (
{
commit({
variables: {
input: {
id: '123',
text: 'text',
},
},
onCompleted(data) {
console.log(data);
},
});
}}
/>
);
}
```
--------------------------------
### GraphQL Subscription Example
Source: https://relay.dev/docs/glossary
Demonstrates the syntax for a GraphQL Subscription, which allows clients to subscribe to server-side data changes. Note the use of the 'subscription' keyword.
```graphql
subscription FeedbackLikeSubscription($input: FeedbackLikeSubscribeData!) {
feedback_like_subscribe(data: $input) {
feedback {
id
like_count
}
}
}
```
--------------------------------
### waitForFragmentData Usage Example
Source: https://relay.dev/docs/api-reference/wait-for-fragment-data
This example demonstrates how to use waitForFragmentData to defer fetching data needed within an event handler.
```APIDOC
## `waitForFragmentData`
### Description
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 avalaible.
To read a fragment's data as it changes over time, see `observeFragment`.
### 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.
```javascript
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 () => {
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 (
My name is {user.name}
Greet
);
}
```
### 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 `.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `$key`. We use our lint rule to enforce that the type of the fragment reference prop is correctly declared.
### Return Value
* A `Promise` where `T` is the data defined in the fragment.
The Promise will wait for all network data to become avaliable as well as any `@live` Relay Resolver 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` or `@required(action: THROW)`, the Promise will reject with an error.
```
--------------------------------
### Use Fragment Example
Source: https://relay.dev/docs/glossary
Demonstrates how to use the useFragment hook to access data from a fragment reference. The fragment reference is obtained from a preloaded query.
```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,
);
```
--------------------------------
### GraphQL Query Example
Source: https://relay.dev/docs/principles-and-architecture/thinking-in-graphql
A sample GraphQL query to fetch a story's text and its author's name.
```graphql
query {
story(id: "1") {
text,
author {
name
}
}
}
```
--------------------------------
### GraphQL: Fetching stories with IDs and text
Source: https://relay.dev/docs/principles-and-architecture/thinking-in-graphql
Illustrates fetching the same data as the REST example but in a single network request using GraphQL.
```graphql
graphql.get(`query { stories { id, text } }`).then(
stories => {
// A list of story items:
// `[ { id: "...", text: "..." } ]`
console.log(stories);
}
);
```
--------------------------------
### GraphQL Query Example
Source: https://relay.dev/docs/glossary
A basic GraphQL query to fetch the actor's name.
```graphql
query Foo {
actor { name }
}
```
--------------------------------
### Integrate ErrorBoundaryWithRetry with useLazyLoadQuery
Source: https://relay.dev/docs/guided-tour/rendering/error-states
This example shows how to use the ErrorBoundaryWithRetry component in your application. It passes a retry function to the fallback UI, allowing users to re-fetch data.
```javascript
/**
* 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 (
<>
{/* Render a button to retry; this will attempt to re-render the
content inside the boundary, i.e. the query component */}
Retry
>
}>
{({fetchKey}) => {
// If we have retried, use the new `retryQueryRef` provided
// by the Error Boundary
return ;
}}
);
}
/**
* MainContent.react.js
*/
function MainContent(props) {
const data = useLazyLoadQuery(
graphql`...`,
variables,
{fetchKey: props.fetchKey}
);
return (/* ... */);
}
```
--------------------------------
### GraphQL Field Redundancy Example
Source: https://relay.dev/docs/principles-and-architecture/compiler-architecture
Illustrates how redundant fields are processed. The 'before' example shows 'id' being processed twice due to nested and conditional selections. The 'after' example shows 'id' processed only once after optimization.
```graphql
foo { # type FooType
id
... on FooType { # matches the parent type, so this is extraneous
id
}
}
# after: `id` is processed once
foo {
id
}
```
--------------------------------
### Set up RelayEnvironmentProvider
Source: https://relay.dev/docs/api-reference/relay-environment-provider
This example demonstrates how to set up the RelayEnvironmentProvider at the root of your application. It includes the necessary imports, a custom fetch function, environment creation, and the provider wrapping the main App component.
```javascript
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 (
);
}
module.exports = Root;
```
--------------------------------
### Basic Test Setup for Preloaded Queries
Source: https://relay.dev/docs/guides/testing-relay-with-preloaded-queries
This snippet demonstrates the fundamental arrangement, act, and assert structure for testing components with preloaded queries. It includes setting up the mock environment, queuing operations, rendering the component, and triggering the query execution.
```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(
);
// 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
});
```
--------------------------------
### Create a Minimal Relay Environment
Source: https://relay.dev/docs/api-reference/relay-runtime/relay-environment
This snippet demonstrates the basic setup for a Relay environment, including defining a fetch function for GraphQL requests and initializing the Store and Network.
```javascript
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),
});
```
--------------------------------
### Basic useQueryLoader Example
Source: https://relay.dev/docs/api-reference/use-query-loader
Demonstrates how to use `useQueryLoader` to fetch and display user data. It includes logic to load the query when a button is clicked and dispose of it when another button is clicked. The `NameDisplay` component uses `usePreloadedQuery` to access the fetched data.
```javascript
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 (
loadQuery({})}> Click to reveal the name
);
}
return (
<>
Click to hide the name and dispose the query.
>
);
}
function NameDisplay({ queryReference }) {
const data = usePreloadedQuery(AppQuery, queryReference);
return {data.user?.name} ;
}
```
--------------------------------
### SkipRedundantNodeTransform Example
Source: https://relay.dev/docs/principles-and-architecture/compiler-architecture
Demonstrates the SkipRedundantNodeTransform's ability to handle complex field duplication. The 'before' example shows 'id' potentially processed up to two times due to unconditional and conditional fetching. The 'after' example shows 'id' processed at most once.
```graphql
# 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
}
}
```
--------------------------------
### Relay Normalized Cache Example
Source: https://relay.dev/docs/principles-and-architecture/thinking-in-graphql
An example of how Relay normalizes and caches a GraphQL response into a flat map of records.
```javascript
Map {
// `story(id: "1")`
1: Map {
text: 'Relay is open-source!',
author: Link(2),
},
// `story.author`
2: Map {
name: 'Jan',
},
};
```
--------------------------------
### Using usePreloadedQuery with useQueryLoader
Source: https://relay.dev/docs/api-reference/use-preloaded-query
This example demonstrates how to use `useQueryLoader` to load a query and then consume its data with `usePreloadedQuery`. The `loadQuery` function is called when a button is clicked, and the `Suspense` boundary handles the loading state.
```javascript
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,
};
function NameLoader(props) {
const [queryReference, loadQuery] = useQueryLoader(
AppQuery,
props.initialQueryRef, /* e.g. provided by router */
);
return (<>
loadQuery({id: '4'})}
disabled={queryReference != null}
>
Reveal your name!
{queryReference != null
?
: null
}
>);
}
function NameDisplay({ queryReference }) {
const data = usePreloadedQuery(AppQuery, queryReference);
return {data.user?.name} ;
}
```
--------------------------------
### Load EntryPoint Reference
Source: https://relay.dev/docs/api-reference/load-entrypoint
This example shows how to load an EntryPoint reference using the loadEntryPoint function. It accesses the Relay environment from context and passes it to loadEntryPoint. Remember to call .dispose() on the returned reference when it's no longer needed, or use useEntryPointLoader for automatic management.
```javascript
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.
```
--------------------------------
### Fragment Spread Example
Source: https://relay.dev/docs/glossary
An example of a fragment spread within a GraphQL query. The fragment `...Component_name` is spread into the `account_user` field.
```graphql
query ComponentQuery {
viewer {
account_user {
...Component_name
}
}
}
```
--------------------------------
### Example Generated TypeScript Type
Source: https://relay.dev/docs/tutorial/queries-1
This is an example of a TypeScript type definition generated by the Relay compiler for a GraphQL query. It outlines the shape of the data that will be returned.
```typescript
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;
};
```
--------------------------------
### Example Relay Field Logger Implementation
Source: https://relay.dev/docs/guides/relay-resolvers/errors
Provides an example of a `relayFieldLogger` function that logs resolver errors to the console. It checks the event kind and logs relevant details about the error and its location.
```javascript
function fieldLogger(event) {
if(event.kind === "relay_resolver.error") {
// Log this somewhere!
console.warn(`Resolver error encountered in ${event.owner}.${event.fieldPath}`)
console.warn(event.error)
}
}
const environment = new Environment({
network: Network.create(/* your fetch function here */),
store: new RelayModernStore(new RecordSource()),
relayFieldLogger: fieldLogger
});
```
--------------------------------
### Creating and Inserting Edges in a Connection
Source: https://relay.dev/docs/api-reference/store
Provides an example of creating a new edge using `ConnectionHandler.createEdge` and then inserting it into a connection either at the beginning using `insertEdgeBefore` or at the end using `insertEdgeAfter`. This is useful for optimistic updates.
```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);
```
--------------------------------
### Using useEntryPointLoader with EntryPointContainer
Source: https://relay.dev/docs/api-reference/use-entrypoint-loader
This example demonstrates how to use `useEntryPointLoader` to conditionally reveal and hide an `EntryPointContainer`. It shows the initial state where the EntryPoint is not loaded, a button to load it, and the state after loading where a button to dispose of it is shown along with the `EntryPointContainer` itself.
```javascript
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 && (
loadEntryPoint({})}>
Click to reveal the contents of the EntryPoint
)
}
{
entryPointReference != null && (
<>
Click to hide and dispose the EntryPoint.
>
)
}
>
);
}
```
--------------------------------
### Using usePaginationFragment with a @connection Fragment
Source: https://relay.dev/docs/api-reference/use-pagination-fragment
This example demonstrates how to use usePaginationFragment to fetch and display a list of friends. It includes setting up the fragment with @argumentDefinitions, @refetchable, and @connection directives, and then using the hook's return values to render data and implement pagination.
```javascript
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 (
<>
Friends of {data.name}:
edge.node)}>
{node => {
return (
{node.name} - {node.age}
);
}}
loadNext(10)}>Load more friends
>
);
}
module.exports = FriendsList;
```
--------------------------------
### Download GraphQL Schema
Source: https://relay.dev/docs/getting-started/quick-start
Fetch the Star Wars GraphQL schema file required by the Relay compiler.
```bash
curl -O https://raw.githubusercontent.com/graphql/swapi-graphql/refs/heads/master/schema.graphql
```
--------------------------------
### Implement Provided Variable Provider
Source: https://relay.dev/docs/api-reference/graphql-and-directives
Implement the 'get' function in a JavaScript module to provide runtime values for a Relay provided variable. The 'get' function must consistently return true or false for a given run.
```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');
},
};
```
--------------------------------
### Querying a Field
Source: https://relay.dev/docs/debugging/why-null
Example of a GraphQL query to fetch a user's name.
```graphql
query MyQuery {
me {
best_friend {
# id: 1
name
}
}
}
```
--------------------------------
### useClientQuery Hook
Source: https://relay.dev/docs/api-reference/use-client-query
Example usage of the `useClientQuery` hook to fetch a client-side field.
```APIDOC
## useClientQuery Hook
### Description
This hook is used to render queries that read only client fields. It allows you to define and query local fields and types that are not sent to the server.
### 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 the specified query.
### Behavior
* This hook works as `useLazyLoadQuery` with `fetchPolicy: store-only`, it does not send the network request.
### Example
```javascript
const React = require('React');
const {graphql, useClientQuery} = require('react-relay');
function ClientQueryComponent() {
const data = useClientQuery(
graphql`
query ClientQueryComponentQuery {
client_field
}
`,
{},
);
return (
{data.client_field}
);
}
```
```
--------------------------------
### getType(): string
Source: https://relay.dev/docs/api-reference/store
Gets the type of the current record, as defined by the GraphQL schema.
```APIDOC
## `getType(): string`
Gets the type of the current record, as defined by the GraphQL schema.
#### Example
```javascript
const type = user.getType(); // User
```
```
--------------------------------
### fetchQuery with .toPromise()
Source: https://relay.dev/docs/api-reference/fetch-query
Demonstrates how to convert a fetchQuery request into a Promise using .toPromise(). It also highlights the recommended practice of avoiding .toPromise() due to potential data processing issues.
```APIDOC
## fetchQuery with .toPromise()
### Description
This example shows how to use the `.toPromise()` method with `fetchQuery` to convert the request into a Promise. It's important to note that `.toPromise()` resolves with the first piece of data and cancels further processing, which can lead to missing deferred or 3D data. Therefore, its use is generally discouraged.
### Method
`fetchQuery(...).toPromise()`
### Endpoint
N/A (SDK Method)
### Parameters
`fetchQuery` takes the following arguments:
- `environment`: The Relay environment to use for the query.
- `graphql`: The GraphQL query to execute.
- `variables`: An object containing the variables for the query.
`.toPromise()` takes no arguments.
### Request Example
```javascript
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 => { ... });
```
### Response
- `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.
```
--------------------------------
### Enable Client 3D with Relay Compiler Configuration
Source: https://relay.dev/docs/guides/data-driven-dependencies/configuration
This configuration enables Client 3D by specifying the dynamic module import mode and the surface for which it should be enabled. Ensure `dynamicModuleProvider.mode` is set to 'Custom' and `surface` is set to 'resolvers' for OSS environments.
```javascript
"moduleImportConfig": {
"dynamicModuleProvider": {
"mode": "Custom",
"statement": "() => require('./.<$module>')"
},
"surface": "resolvers"
}
```
--------------------------------
### Querying a Different Field
Source: https://relay.dev/docs/debugging/why-null
Example of a GraphQL query fetching a different field after a relationship change.
```graphql
query OtherQuery {
me {
best_friend {
# new id: 2
# Note: name is not fetched here
age
}
}
}
```
--------------------------------
### useRefetchableFragment Hook
Source: https://relay.dev/docs/api-reference/use-refetchable-fragment
This example demonstrates how to use the `useRefetchableFragment` hook to refetch a comment fragment with translated text.
```APIDOC
## useRefetchableFragment
### Description
You can use `useRefetchableFragment` when you want to fetch and re-render a fragment with different data.
### 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 queryed by its `id` field. See graphql server specification section 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: `.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 `.graphql.js`, and can be used to declare the type of your `Props`. The name of the fragment reference type will be: `$key`. We use our lint rule to enforce that the type of the fragment reference prop is correctly declared.
### Example Usage
```javascript
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 (
<>
{data.body?.text}
{
refetch({lang: 'SPANISH'}, {fetchPolicy: 'store-or-network'})
}}>
Translate Comment
>
);
}
module.exports = CommentBody;
```
```
--------------------------------
### Using fetchQuery with .toPromise()
Source: https://relay.dev/docs/api-reference/fetch-query
Demonstrates converting a fetchQuery request into a Promise using `.toPromise()`. Note that this method is generally not recommended as it can lead to missing data because it cancels further processing after the first network response.
```javascript
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 => {...};
```
--------------------------------
### Get the data ID of a record
Source: https://relay.dev/docs/api-reference/store
Use `getDataID` on a `RecordProxy` to retrieve its unique identifier within the store.
```javascript
const id = record.getDataID();
```
--------------------------------
### Define a GraphQL Query
Source: https://relay.dev/docs/tutorial/queries-2
This is an example of a basic GraphQL query without variables. It fetches a node by a hard-coded ID.
```graphql
const PosterDetailsHovercardContentsQuery = graphql`
query PosterDetailsHovercardContentsQuery {
node(id: "1") {
... on Actor {
...PosterDetailsHovercardContentsBodyFragment
}
}
}
`;
```
--------------------------------
### Implementing Suspense Sentinel in a Live Resolver
Source: https://relay.dev/docs/guides/relay-resolvers/suspense
Use `suspenseSentinel()` when a Live Resolver's data is not yet available. This example shows how to return the sentinel if the IP address is still loading.
```javascript
import {suspenseSentinel} from 'relay-runtime';
/**
* @RelayResolver Query.myIp: String
* @live
*/
export function myIp(): LiveState {
return {
read: () => {
const state = store.getState();
const ipLoadObject = state.ip;
if (ipLoadObject.status === "LOADING") {
return suspenseSentinel();
}
return state.ip;
},
subscribe: (cb) => {
return store.subscribe(cb);
},
};
}
```
--------------------------------
### Relay Component Testing with Mock Environment
Source: https://relay.dev/docs/guides/testing-relay-components
Use `createMockEnvironment` and `MockPayloadGenerator` from `relay-test-utils` to test components using Relay hooks. This example demonstrates testing loading, data loaded, and error states.
```javascript
// Say you have a component with the useLazyLoadQuery or a QueryRenderer
const MyAwesomeViewRoot = require('MyAwesomeViewRoot');
const {
createMockEnvironment,
MockPayloadGenerator,
} = require('relay-test-utils');
const {act, render} = require('@testing-library/react');
// Relay may trigger 3 different states
// for this component: Loading, Error, Data Loaded
// Here is examples of tests for those states.
test('Loading State', async () => {
const environment = createMockEnvironment();
const renderer = render(
,
);
// Here we just verify that the spinner is rendered
expect(await renderer.findByTestId('spinner')).toBeDefined();
});
test('Data Render', async () => {
const environment = createMockEnvironment();
const renderer = render(
,
);
// Wrapping in act will ensure that components
// are fully updated to their final state.
act(() => {
environment.mock.resolveMostRecentOperation(operation =>
MockPayloadGenerator.generate(operation),
);
});
// 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();
const renderer = render(
,
);
// Wrapping in act will ensure that components
// are fully updated to their final state.
act(() => {
// Error can be simulated with `rejectMostRecentOperation`
environment.mock.rejectMostRecentOperation(new Error('Uh-oh'));
});
expect(await renderer.findByTestId('errorMessage')).toBeDefined();
});
```
--------------------------------
### Display Relay Compiler Help
Source: https://relay.dev/docs/guides/compiler
Shows the help output for the Relay compiler, listing all available commands and options. Useful for exploring advanced features.
```bash
npm run relay --help
```
--------------------------------
### GraphQL: Query for stories with like count
Source: https://relay.dev/docs/principles-and-architecture/thinking-in-graphql
Example GraphQL query to fetch stories including their 'likeCount' field.
```graphql
query { stories { id, text, likeCount } }
```
--------------------------------
### useMutation Hook Usage
Source: https://relay.dev/docs/api-reference/use-mutation
This example demonstrates how to use the useMutation hook to commit a GraphQL mutation and handle the response.
```APIDOC
## `useMutation` Hook
### Description
Hook used to execute a mutation in a React component.
### Arguments
* `mutation`: GraphQL mutation specified using a `graphql` template literal.
* `commitMutationFn`: `(IEnvironment, MutationConfig): Disposable`. __[Optional]__ A function with the same signature as `commitMutation`, which will be called in its stead. Defaults to `commitMutation`.
### Example Usage
```javascript
import type {FeedbackLikeMutation} from 'FeedbackLikeMutation.graphql';
const React = require('React');
const {graphql, useMutation} = require('react-relay');
function LikeButton() {
const [commit, isInFlight] = useMutation(graphql`
mutation FeedbackLikeMutation($input: FeedbackLikeData!) {
feedback_like(data: $input) {
feedback {
id
viewer_does_like
like_count
}
}
}
`);
if (isInFlight) {
return ;
}
return (
{
commit({
variables: {
input: {
id: '123',
text: 'text',
},
},
onCompleted(data) {
console.log(data);
},
});
}}
/>
);
}
```
```
--------------------------------
### Define Client Extension
Source: https://relay.dev/docs/api-reference/use-client-query
Example of extending the Query type with a client-only field using GraphQL schema extensions.
```graphql
# example client extension of the `Query` type
extend type Query {
client_field: String
}
```
--------------------------------
### Configure Network Layer with graphql-ws
Source: https://relay.dev/docs/guided-tour/updating-data/graphql-subscriptions
Configure the Relay Network layer to handle subscriptions using the graphql-ws client. This example demonstrates setting up a WebSocket connection and a subscribe function.
```javascript
import {
...
Network,
Observable
} from 'relay-runtime';
import { createClient } from 'graphql-ws';
const wsClient = createClient({
url:'ws://localhost:3000',
});
const subscribe = (operation, variables) => {
return Observable.create((sink) => {
return wsClient.subscribe(
{
operationName: operation.name,
query: operation.text,
variables,
},
sink,
);
});
}
const network = Network.create(fetchQuery, subscribe);
```
--------------------------------
### Load a Query with loadQuery
Source: https://relay.dev/docs/api-reference/load-query
Demonstrates how to use loadQuery to fetch data. Note that query references must have .dispose() called on them, which is omitted here for brevity. Avoid calling loadQuery at the top level; prefer event-driven calls.
```javascript
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.
```
--------------------------------
### get(dataID: string): ?RecordProxy
Source: https://relay.dev/docs/api-reference/store
Retrieves a record from the store given its `dataID`. Returns a `RecordProxy` for mutating the record.
```APIDOC
## `get(dataID: string): ?RecordProxy`
Retrieves a record from the store given its `dataID`. Returns a `RecordProxy` which serves as an interface to mutate the record.
#### Example
```javascript
const record = store.get(dataID);
```
```
--------------------------------
### Render Query with `useLazyLoadQuery`
Source: https://relay.dev/docs/guided-tour/refetching/refetching-queries-with-different-data
Use the `useLazyLoadQuery` hook to fetch and render data based on provided query variables and options. A button is included to trigger the refetch function.
```javascript
/**
* 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 (
<>
{data.user?.name}
Friends count: {data.user.friends?.count}
refetch()}>
Fetch latest count
>
);
}
```
--------------------------------
### GraphQL Subscription Query with Fragment Spreads
Source: https://relay.dev/docs/guided-tour/updating-data/graphql-subscriptions
This example shows how to structure a subscription query to refresh specific components by spreading their fragments. This approach ensures that components dependent on the updated data are re-rendered efficiently.
```graphql
subscription FeedbackLikeSubscription($input: FeedbackLikeSubscribeData!) {
feedback_like_subscribe(data: $input) {
feedback {
...FeedbackDisplay_feedback
...FeedbackDetail_feedback
}
}
}
```
--------------------------------
### Get the type of a record
Source: https://relay.dev/docs/api-reference/store
The `getType` method on a `RecordProxy` returns the record's type name as defined in the GraphQL schema.
```javascript
const type = user.getType(); // User
```
--------------------------------
### List Available Relay Codemods
Source: https://relay.dev/docs/guides/codemods
Run the `relay codemod --help` command to see a list of available codemods and their descriptions. This command also shows usage instructions and available options.
```bash
> relay codemod --help
Apply codemod (verification with auto-applied fixes)
Usage: relay codemod [OPTIONS] [CONFIG]
Commands:
mark-dangerous-conditional-fragment-spreads Marks unaliased conditional fragment spreads as @dangerously_unaliased_fixme
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 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
```
--------------------------------
### Querying for Rebels Data
Source: https://relay.dev/docs/guides/graphql-server-specification
Example GraphQL query to fetch the ID and name of the 'rebels' faction. This demonstrates basic data fetching.
```graphql
query RebelsQuery {
rebels {
id
name
}
}
```
--------------------------------
### After Client 3D Component Implementation
Source: https://relay.dev/docs/guides/data-driven-dependencies/client-3d
This component demonstrates the structure after implementing Client 3D. It utilizes separate fragments with the @module directive and a MatchContainer for dynamic rendering based on the fetched data.
```javascript
const {graphql, useFragment, useClientQuery, MatchContainer} = require('react-relay');
component Client3DRelayRenderer() {
const FOO_FRAGMENT = graphql`
fragment Client3DFooComponent_Fragment on Client3DFoo {
data {
type
info
}
}
`;
const BAR_FRAGMENT = graphql`
fragment Client3DBarComponent_Fragment on Client3DBar {
data {
type
info
}
}
`;
const HELLO_WORLD_FRAGMENT = graphql`
fragment Client3DHelloWorldComponent_Fragment on Client3DHelloWorld {
data {
type
info
}
}
`;
const client3DData = useClientQuery(
graphql`
query Client3DRelayQuery {
client3D {
...Client3DFooComponent_Fragment
@module(name: "Client3DFooComponent.react")
...Client3DBarComponent_Fragment
@module(name: "Client3DBarComponent.react")
...Client3DHelloWorldComponent_Fragment
@module(name: "Client3DHelloWorldComponent.react")
}
}
`
);
return (
);
}
```
--------------------------------
### Successful GraphQL Mutation Response
Source: https://relay.dev/docs/guided-tour/updating-data/graphql-mutations
An example of a successful response after executing a GraphQL mutation. It shows the updated fields for the modified data.
```json
{
"feedback_like": {
"feedback": {
"id": "feedback-id",
"viewer_does_like": true,
"like_count": 1,
}
}
}
```