在 Apollo 客户端中使用 GraphQL 指令
配置 GraphQL 字段和片段
A指令 装饰 GraphQL 模式或操作的部分,并附带额外配置。如 Apollo 客户端等工具可以读取 GraphQL 文档的指令,并根据需要进行自定义逻辑。
指令 在字符 @
之后,如下所示:
query myQuery($someTest: Boolean) {experimentalField @skip(if: $someTest)}
此示例显示的是 @skip
指令,这是一个内置指令(即,它是
GraphQL规范)。它展示了关于指令的以下内容:
- 指令可以接受其自己的参数(在本例中为
if
)。 - 指令出现于它们修饰的内容声明之后(在本例中为
experimentalField
的字段)。
@client
该@client
指令允许您在与服务器数据一起解析仅客户端数据。这些字段不会发送到GraphQL服务器。
query LaunchDetails($launchId: ID!) {launch(id: $launchId) {siterocket {type# resolved locally on the client,# removed from the request to the serverdescription @client}}}
有关@client
指令的更多信息,请参阅此部分关于仅本地字段。该@client
指令还适用于在应用程序所消耗的GraphQL API支持特定的字段之前进行客户端模式模拟。
@connection
该@connection
指令允许您为分页结果指定自定义缓存键。更多信息,请参阅此部分关于@connection
指令。
query Feed($offset: Int, $limit: Int) {feed(offset: $offset, limit: $limit) @connection(key: "feed") {...FeedFields}}
@defer
从版本3.7.0
开始,Apollo Client提供了@defer指令的预览支持。此指令允许您的查询增渐进式地接收特定字段的数据,而不是同时在同一时间接收所有字段的数据。这在需要字段中某些字段比其他字段resolve更长时非常有用。
要使用 @defer
指令,我们将其应用于包含所有慢加载字段片段 的内联或命名片段:
query PersonQuery($personId: ID!) {person(id: $personId) {# Basic fields (fast)idfirstNamelastName# Friend fields (slower)... @defer {friends {id}}}}
注意:要在 React Native 应用程序中使用 @defer
,需要额外的配置。有关更多信息,请参阅 React Native 文档。
有关 @defer
指令的更多信息,请查看 @defer
文档。
@export
如果你的 GraphQL 查询使用了 变量,则该查询的本地字段可以提供这些变量的值。
为此,你可以应用类似下面的 @export(as: "variableName")
指令:
const GET_CURRENT_AUTHOR_POST_COUNT = gql`query CurrentAuthorPostCount($authorId: Int!) {currentAuthorId @client @export(as: "authorId")postCount(authorId: $authorId)}`;
在上面的查询中,本地字段 currentAuthorId
的结果用作传递给 postCount
的 $authorId
变量的值。
即使 postCount
也是一个仅本地字段(即,如果它也被标记为 @client
),你也可以这样做。
有关使用 @export
指令的更多信息和其他注意事项,请参阅 仅本地字段文档。
@nonreactive
Since3.8.0
使用 @nonreactive
指令可以标记查询字段或片段扩展,并表示标记为 @nonreactive
的子树中的数据更改不应触发重新渲染。这允许父组件在子组件的渲染数据时获取数据,而不需要在 @nonreactive
标记的字段更改时重新渲染自己。
考虑一个 App
组件,它获取并渲染一组滑雪道列表:
const TrailFragment = gql`fragment TrailFragment on Trail {namestatus}`;const ALL_TRAILS = gql`query allTrails {allTrails {id...TrailFragment @nonreactive}}${TrailFragment}`;function App() {const { data, loading } = useQuery(ALL_TRAILS);return (<main><h2>Ski Trails</h2><ul>{data?.trails.map((trail) => (<Trail key={trail.id} id={trail.id} />))}</ul></main>);}
组件 Trail
渲染滑雪道的名称和状态,并允许用户执行 变异操作 以在 "OPEN"
和 "CLOSED"
之间切换滑雪道的状态:
const Trail = ({ id }) => {const [updateTrail] = useMutation(UPDATE_TRAIL);const { data } = useFragment({fragment: TrailFragment,from: {__typename: "Trail",id,},});return (<li key={id}>{data.name} - {data.status}<inputchecked={data.status === "OPEN" ? true : false}type="checkbox"onChange={(e) => {updateTrail({variables: {trailId: id,status: e.target.checked ? "OPEN" : "CLOSED",},});}}/></li>);};
注意,组件 Trail
没有通过 props 接收整个 trail
对象,只接收 id
。该 id
与羽毛文档一起使用来为缓存中的每个滑雪道项创建一个实时绑定。这使得每个 Trail
组件可以独立地对单个滑雪道的缓存更新做出反应。对滑雪道 状态
的更新不会导致父组件 App
重新渲染,因为 @nonreactive
指令已应用于 TrailFragment
扩展,这是一个包含 status
字段的 fragment。