### 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 ( ); } ``` ### 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 */} }> {({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 ( ); } return ( <> ); } 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 (<> {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 && ( ) } { entryPointReference != null && ( <> ) } ); } ``` -------------------------------- ### 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}
); }}
); } 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}

); } 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 ( ); } ``` -------------------------------- ### 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, } } } ```