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?
The code addresses the original concerns as follows:
Avoiding Component Splitting: The code keeps the component as a single unit (App) rather than splitting it into multiple components, simplifying the code structure.
Passing User Data as a Prop: It passes the user data as a prop (user) to the component, making it easier to work with and avoiding tight coupling with Relay-specific functionality.
Fetching Data on Component Mount: It uses the useEffect hook to fetch data when the component mounts, ensuring that the data is available before rendering and reducing the delay in displaying new entries when redirected.