API: 带查询的 graphql 容器
本文详细介绍
graphql()高阶组件的查询使用。要查看关于所有操作的选项,请参阅一般graphql容器API文档。
你传递给 graphql() 函数的操作决定了组件的行为方式。如果你将查询传递到 graphql() 函数中,那么你的组件将执行该查询并响应监听 store 中查询的更新。
使用 graphql() 函数执行查询的示例组件:
|
|
有关 graphql() 函数查询的理论概述,请阅读查询文档。要了解 graphql() 函数支持的所有有关查询的功能,请往下读。
props.data
使用 graphql() 创建的高阶组件会将一个 data 参数传给你的组件。像这样:
|
|
data 属性包含从查询中获取的数据,另外还有一些有用的属性和方法,可以用来控制 GraphQL 连接组件的生命周期。例如,我们有一个如下所示的查询:
|
|
你的 data prop 将会包含此数据:
|
|
data prop 还有一些有用的属性,可以直接从 data 对象访问。例如 data.loading 或 data.error。
具体来说,首先要确保在渲染之前始终检查你的组件中的 data.loading 和 data.error 属性,因为包含应用数据的 data.todos 等属性,在你的组件正在执行初始查询时可能尚未定义。检查 data.loading 和 data.error 可以帮助你避免任何未定义数据的问题。此类检查可能如下所示:
|
|
data.loading
这是一个表示该组件当前是否正在执行查询请求的布尔值。该值为真时,意味着正在使用你的网络接口发送查询请求,并且还没有得到响应。一般使用此属性渲染 loading 组件。
但是,如果 data.loading 值为 true,并不意味着你没有数据。举个例子,如果你已经有 data.todos 数据,但是你想从你的 API 中获取最新的 todos,此时,data.loading 可能为真,但是你仍然能访问你之前请求的 todos。
你请求的查询可能存在多种不同的网络状态。如果要更详细地了解组件的网络状态,请参阅 data.networkStatus。
例:
|
|
data.error
如果请求发生错误,那么该属性将被赋值为 ApolloError 的一个实例。如果你不处理此错误,你将在控制台中收到一条警告信息:"Unhandled (in react-apollo) Error: ..."。
例:
|
|
data.networkStatus
如果要根据网络状态显示不同的加载指示符(或根本没有指示符),则 data.networkStatus 非常有用,因为它为组件提供了比 data.loading 更详细的有关网络状态的信息。data.networkStatus 的值类型是一个1至8之间不同数字值的枚举,这些数值各自表示不同的网络状态。
loading:查询运行之后,且请求仍处于待处理状态。即使在高速缓存中命中结果,查询请求仍然具有此网络状态,但是查询已被调度。setVariables:如果查询的变量发生变化,且网络请求被触发,则网络状态为setVariables,直到该查询的结果返回。当options.variables对查询进行更改时,React 用户会感受到这一点。fetchMore:表示在这个查询中调用了fetchMore,并且所创建的网络请求当前正在运行。refetch:这意味着refetch在该查询中被调用,并且 refetch 请求当前正在运行。- 未用到。
poll:表示当前轮询查询正在运行。因此,假设如果你每10秒钟轮询一次查询,那么当轮询请求发送但未解决时,网络状态将每10秒切换到poll。ready:当前查询没有请求正在运行,且没有发生错误,一切安好。error:当前查询没有请求正在运行,但检测到一个或多个错误。
如果网络状态小于7,则相当于 data.loading 为真。实际上,你可以用 data.networkStatus < 7 替换所有的 data.loading 检查,尽管没有什么区别,但建议你使用 data.loading。
例:
|
|
data.variables
Apollo 用来从 GraphQL 端点获取数据的变量。如果要根据向服务端发送请求的变量呈现某些信息,此属性将非常有用。
例:
|
|
data.refetch(variables)
强制你的组件重新执行你在 graphql() 函数中定义的查询。当你要重新加载组件中的数据,或者在错误发生后重试请求时,此方法将会很有用。
data.refetch 返回一个 promise,一旦查询执行结束,就会将你的 API 中获取的新数据解析出来。如果查询失败,promise 将会 reject。
data.refetch 函数接收一个 variables 对象参数。variables 参数将替换查询选项或 graphql() 高阶组件(根据你是否指定了一个 query)选项来重新请求你在 graphql() 函数中定义的查询。
例:
|
|
data.fetchMore(options)
data.fetchMore 功能可以让你对查询组件进行分页。要了解更多有关使用 data.fetchMore 分页的信息,请务必阅读分页说明,其中包含如何使用 React Apollo 进行分页的有用插图。
data.fetchMore 返回一个 Promise,一旦请求更多数据的查询 resolve,该 Promise 立即 resolve。
data.fetchMore 函数使用一个 options 对象作为参数。options 参数可能具有以下属性:
[query]:这是使用gqlGraphQL 标签创建的可选 GraphQL 文档。如果你指定了一个query,那么当你调用data.fetchMore的时候,该查询将被执行。如果没有指定query,那么将使用graphql()高阶组件的查询。[variables]:作为一个可选变量,将与query选项或graphql()高阶组件中的查询一起使用(取决于你是否指定了一个query)。updateQuery(previousResult, { fetchMoreResult, queryVariables }):这是由你定义的必要函数,将会实际更新你的分页列表。第一个参数previousResult将会是你在graphql()函数中定义的查询返回的之前的数据。第二个参数是一个具有两个属性fetchMoreResult和queryVariables的对象。fetchMoreResult是新请求返回的数据,它由data.fetchMore的query和variables选项得来。queryVariables是请求更多数据时使用的变量。通过指定这些参数,你将会得到一个服务端返回的新的数据对象,该对象与你在graphql()函数中定义的 GraphQL 查询具有相同形式。请参考下面的示例,并确保阅读具有完整示例的分页 说明。
例:
|
|
data.subscribeToMore(options)
该函数将设置一个订阅,每当服务器发送订阅发布时将触发更新。这需要在服务器上设置订阅才能正常工作。查看订阅指南 ,subscriptions-transport-ws 和 graphql-subscriptions 获取更多相关信息。
该函数返回一个 unsubscribe 函数处理器,用以在之后取消订阅。
通常的做法是将 subscribeToMore 封装到 componentWillReceiveProps 中供组件调用,并在原始查询完成后执行订阅。为确保订阅不会被多次创建,你可以将其附加到组件实例。更多详细信息,请参考示例。
[document]:Document 是一个必需的属性,它接受用graphql-tag的gql模板字符串标签创建的 GraphQL 订阅文档。它应该包含一个指定返回数据的 GraphQL 订阅操作。[variables]:作为可选变量将与document选项一起使用。[updateQuery]:每次服务器发送更新时运行的可选函数。它将修改高阶组件查询的结果。第一个参数previousResult将是你在graphql()函数中定义的查询之前返回的数据。第二个参数是一个具有两个属性的对象。subscriptionData是订阅的结果。variables是与订阅查询一起使用的变量对象。使用这些参数,你应该返回一个与你在graphql()函数中定义的 GraphQL 查询相同形状的新的数据对象。这与fetchMore回调类似。或者,你可以使用 reducer 作为你的graphql()函数的options 的一部分来更新查询。[onError]:一个可选的错误回调。
如果要使用订阅结果更新查询的 store,你必须在 graphql() 函数中指定 subscribeToMore 的 updateQuery 选项或 reducer 选项。
例:
|
|
data.startPolling(interval)
该函数将设置一个时间间隔,每隔一段固定时间便发送请求。该函数只有一个整数参数,允许你配置以毫秒为单位执行查询的频率。换句话说,interval 参数表示轮询之间的毫秒数。
轮询是将UI中的数据保持更新的好方法。通过每5000毫秒(例如5秒钟)重新获取数据,你可以有效地模拟实时数据,而无需建立实时后端。
当查询已经在执行轮询时,如果你调用 data.startPolling,那么当前的轮询操作将被取消,并且以指定的时间间隔开始一个新的轮询操作。
你也可以使用 options.pollInterval,在你的组件挂载后立即开始轮询。如果你不需要任意地启动和停止轮询,建议你使用 options.pollInterval。
如果你将 interval 设置为0,那么这意味着没有轮询,而不是每个 JavaScript 事件循环滴答均执行一次请求。
例:
|
|
data.stopPolling()
通过调用此函数,你可以终止任意当前正在执行的轮询操作。在你调用 data.startPolling 之前,你的查询将不会再次发起轮询。
例:
|
|
data.updateQuery(updaterFn)
该函数允许你在任何突变,订阅或请求的上下文之外更新查询的数据。该函数只接收另一个函数作为它单独的参数。函数参数具有以下特征:
|
|
第一个参数是 store 中当前存在的查询的数据,并且你期望返回具有相同形状的新数据对象。该新数据对象将被写入 store,并且跟踪该数据的任何组件都将会响应更新。
第二个参数是一个具有单个属性 variables 的对象。variables 属性允许你从 store 中读取 previousResult 时查看其使用的变量。
此方法不会更新服务器上的任何东西。它只会更新客户端缓存中的数据,如果你重新加载 JavaScript 环境,则更新将消失。
例:
|
|
config.options
返回用于配置如何获取和更新查询的选项对象的对象或函数。
如果 config.options 是一个函数,那么它将以组件的 props 为第一个参数。
可用于此对象的选项取决于你为 graphql() 的第一个参数传入的操作类型。以下参考文档将记录你的操作是查询时哪些选项可用。要查看其他用于不同操作的选项,请参阅 config.options 的通用文档。
例:
|
|
|
|
options.variables
The variables that will be used when executing the query operation. These variables should correspond with the variables that your query definition accepts. If you define config.options as a function then you may compute your variables from your props.
执行查询操作时将使用的变量。这些变量应与查询定义接受的变量相对应。如果你定义 config.options 为一个函数,那么你可以从你的 props 计算你的变量。
例:
|
|
options.fetchPolicy
fetchPolicy 是一个选项,可让你指定组件如何与 Apollo 数据缓存进行交互。默认情况下,你的组件将首先尝试从缓存中读取数据,如果查询的完整数据位于缓存中,则 Apollo 将从缓存中直接返回该数据。如果你的查询的完整数据不在缓存中,则 Apollo 将使用你的网络接口执行你的请求。通过更改此选项,你可以更改默认行为。
fetchPolicy 有效值有:
cache-first:作为默认值,在该策略下,我们始终尝试从缓存中读取数据。如果完成查询所需的所有数据都在缓存中,那么该数据将被返回。如果缓存结果不可用,Apollo 将只会从网络中请求。该请求策略旨在最大限度地减少渲染组件时发送的网络请求数。cache-and-network:该请求策略将让 Apollo 首先尝试从缓存中读取数据。如果完成查询所需的所有数据都在缓存中,那么该数据将被返回。但是,无论你的缓存中是否存在完整数据,fetchPolicy将始终通过网络接口执行查询,不同于cache-first,只有当查询数据不在缓存中时,才执行查询。该请求策略优化使得用户获得快速响应,同时尝试将高速缓存的数据与服务器数据保持一致,但需要额外的网络请求。network-only:该请求策略将永远不会从缓存中返回初始数据。相反,它将始终使用你的网络接口向服务器发出请求。该请求策略优化是为了与服务器的数据保持一致,但是牺牲了响应在可用时立即返回给用户的及时性。cache-only:该请求策略将永远不会使用你的网络接口执行查询。相反,它将始终尝试从缓存中读取数据。如果查询的数据不存在于缓存中,则会抛出错误。该请求策略允许你只与本地客户端缓存中的数据进行交互,而不会发生任何网络请求,从而保持组件快速响应,但意味着你的本地数据可能与服务器上的数据不一致。如果你只对 Apollo Client 缓存中的数据进行交互感兴趣,那么请务必查阅你的ApolloClient实例中可用的readQuery()和readFragment()方法。
例:
|
|
options.pollInterval
表示你要开始轮询的间隔(以毫秒为单位)。无论何时经过这个毫秒数,你的查询将使用网络接口执行,下一个执行将使用配置的毫秒数进行调度。
当组件挂载时,此选项将立即开始轮询你的查询。如果要动态启动和停止轮询,则可以使用 data.startPolling 和 data.stopPolling。
如果将 options.pollInterval 设置为0,那么这意味着不会执行轮询,每个 JavaScript 事件循环滴答都不会执行请求。
例:
|
|
options.notifyOnNetworkStatusChange
更新网络状态或网络错误是否会触发组件的重新渲染。
默认值为 false。
例:
|
|