在 Apollo 客户端中使用 @defer 指令
增量接收查询响应数据
从版本3.7.0
开始Apollo Client支持对@defer
指令的预览支持。这个指令允许您的查询接收对特定字段的逐步数据的获取,而不是一次性得到所有字段数据。这对于查询中的一些字段需要比其他字段花费更长的时间进行解析时非常有用。
为了成功地将字段延迟处理,被查询的端点必须也支持@defer
指令。实体基础的@defer
支持在GraphOS Router中已进入通用可用阶段,并且与所有联邦兼容的子图库兼容。
示例
假设我们正在构建一个社交媒体应用程序,它可以快速获取用户的个人资料信息,但获取该用户的友友信息需要较长时间。
GraphQL允许我们在单个查询中声明UI所需的全部字段,但这也意味着我们的查询的响应速度将与解析速度最慢的字段一样慢。使用@defer指令允许我们标记查询中对于应用程序初始渲染不是必要的部分,这将一旦可用就被解析。.
为了实现这一点@defer
指令到包含所有与友友数据相关的慢解析字段片段中:
query PersonQuery($personId: ID!) {person(id: $personId) {# Basic fields (fast)idfirstNamelastName# Friend fields (slower)... @defer {friends {id}}}}
使用这种语法,如果查询服务器支持 @defer
,我们的客户端可以首先在初始响应负载中接收“基本字段”,然后是包含“朋友字段”的附加负载。
让我们以React为例。这里我们可以假设GET_PERSON
是上述查询,即PersonQuery
,带有延迟的朋友id
列表:
import { gql, useQuery } from "@apollo/client";function App() {const { loading, error, data } = useQuery(GET_PERSON, {variables: {id: 1,},});if (loading) return "Loading...";if (error) return `Error! ${error.message}`;return (<>Welcome, {data.firstName} {data.lastName}!<details><summary>Friends list</summary>{data.friends ? (<ul>{data.friends.map((id) => (<li>{id}</li>))}</ul>) : null}</details></>);}
当后续的延迟数据块到达时,useQuery
将重新渲染(由于延迟的多部分响应之间的重新渲染,loading
保持为false
)并且当它们到达时,data
将包含延迟数据。
因此,@defer
可以被视为一种工具,用于提高初始渲染速度,因为一些较慢的数据将在页面底部或屏幕外显示。在这种情况下,我们在默认关闭的<details>
元素内部渲染朋友列表,避免了当friends
数据到达时的布局偏移。
使用与代码生成
如果您目前正在使用 GraphQL Code Generator 来满足您的代码生成需求,您需要使用 4.0.0 或更高版本的 Codegen。请参阅 Codegen 文档 以获取更多信息。
在 React Native 中的使用
为了在 React Native 应用中使用 @defer
,需要配置额外的设定。请参阅 React Native 文档 以获取更多信息。