0
Example from the documentation:
import type {AppQueryType} from 'AppQueryType.graphql';
const React = require('React');
const {graphql, useQueryLoader, usePreloadedQuery} = require('react-relay');
const AppQuery = graphql`
query AppQuery($id: ID!) {
user(id: $id) {
name
}
}
`;
type Props = {
initialQueryRef: PreloadedQuery<AppQueryType>,
};
function NameLoader(props) {
const [queryReference, loadQuery] = useQueryLoader(
AppQuery,
props.initialQueryRef, /* e.g. provided by router */
);
return (<>
<Button
onClick={() => loadQuery({id: '4'})}
disabled={queryReference != null}
>
Reveal your name!
</Button>
<Suspense fallback="Loading...">
{queryReference != null
? <NameDisplay queryReference={queryReference} />
: null
}
</Suspense>
</>);
}
function NameDisplay({ queryReference }) {
const data = usePreloadedQuery(AppQuery, queryReference);
return <h1>{data.user?.name}</h1>;
}
Too complicated. First, I don’t want to split the initial component to NameLoader
and NameDisplay
only because it is convenient for the Relay. Second, even I have the child component, I don’t want the PreloadedQuery
be among props
because it is the tight copulation of the Relay and the simple React component (it means the replacing of the Relay with something else will entail the editing of all components such NameDisplay
). Instead I want to pass the normal data via props
, such the user
object.
The desired code will be like:
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
}
}
`;
function NameLoader(props) {
const rawUser = useMagic(AppQuery);
const [ user, setUser ] = toLocalState(rawUser);
return (<>
<Button
onClick={() => loadQuery({id: '4'})}
disabled={queryReference != null}
>
Reveal your name!
</Button>
<h1>{user.name}</h1>;
</>);
}
I understand that the data fetching is the asynchronous but it sould not mean that what Realy suggesting in the only correct solution.
From the const [ user, setUser ] = toLocalState(rawUser);
line, I want to work with the user
variable as with normal local state. In this example, I don’t care that local changes with user
will not reflect on user
at server side – when I’ll be ready for reflecting, I’ll invoke the appropriate mutation.
What will be instead of useMagic
and toLocalState
?
1 Answer
Reset to default
0
It seems like you’re looking for a way to manage the data retrieved from GraphQL using Relay in a more straightforward manner without relying on the structure provided by Relay’s hooks. You want to convert the data to a more traditional React state pattern. While this approach might not leverage Relay’s optimizations fully, you can achieve what you’re looking for by combining the useLazyLoadQuery
hook and local React state.
Here’s how you can achieve that using your example:
import type { AppQueryType } from 'AppQueryType.graphql';
import React, { useState } from 'react';
import { graphql, useLazyLoadQuery } from 'react-relay';
const AppQuery = graphql`
query AppQuery($id: ID!) {
user(id: $id) {
name
}
}
`;
function NameLoader() {
const [userId, setUserId] = useState(null); // User ID state
const data = useLazyLoadQuery<AppQueryType>(AppQuery, { id: userId });
return (
<>
<Button onClick={() => setUserId('4')} disabled={userId != null}>
Reveal your name!
</Button>
{data.user ? <h1>{data.user.name}</h1> : null}
</>
);
}
In this example, I’ve used the useLazyLoadQuery
hook to fetch the data when the user ID changes. When the button is clicked, the userId
state is updated, causing the query to fetch the user data. The fetched user data is stored in the data
variable.
Please note that by using this approach, you’re not taking full advantage of Relay’s optimizations, but it provides a more familiar React state management approach. If you later decide to use Relay’s optimizations more extensively, you might need to refactor your components to adhere to Relay’s conventions more closely.
3
-
Thank you for the answer. Would you please to tell me how I can change the
data
correctly? Maybe viaconst [ dataState, setDate ] = useState(data)
? Is it fine during re-rendering?– Takeshi Tokugawa YD45 mins ago
-
2
@TakeshiTokugawaYD Just a heads up, this user is serially relying on ChatGPT to generate and post answers, which is prohibited. It's likely this user doesn't have any real knowledge about GraphQL or RelayJS, and it's not worth interacting with them.
– Sean29 mins ago
-
@Sean Thank you for the alert but… How have you knew it?
– Takeshi Tokugawa YD25 mins ago