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>;
}
太复杂了。首先,我不想将初始组件拆分为
NameLoader
和 NameDisplay
只是因为这样对于 Relay 来说方便。其次,即使我有子组件,我也不希望 PreloadedQuery
位于 props
之中,因为它是 Relay 和简单 React 组件的紧密结合(这意味着用其他组件替换 Relay 将需要所有组件的编辑,例如NameDisplay
)。相反,我想通过 props
传递普通数据,例如 user
对象。
所需的代码将类似于:
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>;
</>);
}
我知道数据获取是异步的,但这并不意味着真正建议的唯一正确的解决方案。
从
const [ user, setUser ] = toLocalState(rawUser);
行,我想像正常本地状态一样使用 user
变量。在此示例中,我不关心 user
的本地更改不会反映在服务器端的 user
上 - 当我准备好反映时,我将调用适当的突变。
用什么来代替
useMagic
和 toLocalState
?
您似乎正在寻找一种方法,以更直接的方式管理使用 Relay 从 GraphQL 检索的数据,而不依赖于 Relay 钩子提供的结构。您想要将数据转换为更传统的 React 状态模式。虽然这种方法可能无法充分利用 Relay 的优化,但您可以通过结合
useLazyLoadQuery
钩子和本地 React 状态来实现您想要的目标。
以下是如何使用示例实现这一目标:
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}
</>
);
}
在此示例中,我使用
useLazyLoadQuery
钩子在用户 ID 更改时获取数据。单击该按钮时,userId
状态会更新,从而导致查询获取用户数据。获取的用户数据存储在 data
变量中。
请注意,通过使用这种方法,您并没有充分利用 Relay 的优化,但它提供了更熟悉的 React 状态管理方法。如果您稍后决定更广泛地使用 Relay 的优化,您可能需要重构您的组件以更严格地遵守 Relay 的约定。