使用 Apollo 重新获取部分 GraphQL 查询的最佳实践?

Best practices for refetching part of a GraphQL query with Apollo?

我有以下 react-apollo-wrapped GraphQL 查询:

user(id: 1) {
  name
  friends {
    id
    name
  }
}

作为语义表示,它获取 ID 为 1 的用户,returns 其 name,并且 returns 所有的 idname它的朋友们。

然后我将其呈现在如下组件结构中:

graphql(ParentComponent)
  -> UserInfo
  -> ListOfFriends (with the list of friends passed in)

这一切都对我有用。但是,我希望能够重新获取当前用户的好友列表。

我可以在父组件上执行 this.props.data.refetch() 并且更新将被传播;但是,鉴于我的 GraphQL 查询看起来更像这样,我不确定这是最佳做法,

user(id: 1) {
  name
  foo1
  foo2
  foo3
  foo4
  foo5
  ...
  friends {
    id
    name
  }
}

虽然我唯一想重新获取的是朋友列表。

干净地构建它的最佳方法是什么?我正在考虑将最初跳过的 GraphQL 提取器绑定到 ListOfFriends 组件,该组件可以根据需要触发,但希望获得一些关于如何最好地完成此操作的指导。

提前致谢。

我不知道为什么你的问题被否决了,因为我认为这是一个非常有效的问题。 GraphQL 的卖点之一是 "fetch less and more at once"。客户可以从后端非常精细地决定它需要什么。使用以前需要多个端点的深度嵌套的图形查询现在可以在单个查询中表达。同时可以避免过度获取。现在您发现自己有一个大查询,所有内容都立即加载并且没有 n+1 查询瀑布。但是现在您知道您的大查询中的一些字段不时会发生变化,并且您希望使用来自服务器的新数据主动更新缓存。 Apollo 提供了 refetch 字段,但它加载了整个查询,这显然是 overfetching 卖给我的,因为在 GraphQL 中不再是一个问题。让我提供一些解决方案:

过早优化?

The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming. - Donald Knuth

有时我们会在没有先测量的情况下尝试优化太多。先用简单的方法写,然后看看它是否真的是个问题。到底什么是慢?网络?查询中的特定字段?查询的绝对大小?

在您分析出究竟是什么速度慢之后,我们可以开始着手改进:

Refetch 和 include/skip 指令

使用 directives you can exclude fields from a query depending on variables. The refetch function can specify different variables 比初始查询。这样您就可以在重新获取查询时排除字段。

拆分查询

单页应用是个好主意。 HTML 是在客户端生成的,页面不必昂贵地访问服务器来呈现新页面。但很快 SPA 变得很大,代码拆分成为一个问题。现在我们基本上回到服务器端渲染并将应用程序拆分为页面。这同样适用于 GraphQL。有时查询太大,应该拆分。您可以拆分 UserInfoListOfFriends 的查询。在缓存内部,字段将被合并。使用 query batching both queries will be send in the same request and a GraphQL server that implements per request resource caching correctly (e.g. with Dataloader) 几乎不会注意到差异。

订阅

也许您已经准备好使用订阅了。订阅从服务器发送已更改字段的更新。这样您就可以订阅用户的朋友并实时获得更新。好消息是 Apollo Client、Relay 和许多服务器实现已经提供了对订阅的支持。坏消息是它需要 websockets,通常对您的技术堆栈提出与纯 HTTP 不同的要求。

withApollo() -> this.client.query

这应该是你最后的选择!使用 react-apollowithApollo 高阶组件,您可以直接注入 ApolloClient 实例。您现在可以使用 this.client.query() 执行查询。 { user(id: 1) { friendlist { ... } } } 可用于仅获取好友列表并更新缓存,这将导致组件更新。这可能看起来像您想要的,但可能会在应用程序的后期阶段困扰您。