我有以下react-apollo
- 包装的GraphQL查询:
user(id: 1) {
name
friends {
id
name
}
}
以语义表示,它会提取ID为1的用户,返回其name
,并返回其所有朋友的id
和name
。
然后我在如下组件结构中呈现它:
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
组件,这可以在必要时触发,但是想要了解如何最好地完成此操作。
提前致谢。
答案 0 :(得分:11)
我不知道为什么你的问题被贬低,因为我认为这是一个非常有效的问题。 GraphQL的一个卖点是“一次性获取更少”。客户可以从后端非常简单地决定它需要什么。使用以前需要多个端点的深层嵌套图形查询现在可以在单个查询中表示。同时可以避免过度取样。现在你发现自己有一个大查询,一切都加载,并且没有n + 1个查询瀑布。但是现在您知道大查询中的一些字段可能会随时更改,并且您希望使用服务器中的新数据主动更新缓存。 Apollo提供了refetch
字段,但它加载了整个查询,这显然是 overfetching ,这些查询已经卖给我,因为GraphQL中不再是一个问题。让我提供一些解决方案:
真正的问题是程序员花了太多时间在错误的地方和错误的时间担心效率;过早优化是编程中所有邪恶(或至少大部分)的根源。 - Donald Knuth
有时我们会尝试优化太多而不先测量。先写一下简单的方法,然后看看它是否真的是一个问题。究竟什么慢?网络?查询中的特定字段?查询的大小?
在你分析了究竟什么是慢的之后我们可以开始研究改进了:
使用directives,您可以根据变量从查询中排除字段。 refetch function can specify different variables比初始查询。这样,您可以在重新获取查询时排除字段。
单页应用是个好主意。 HTML是在客户端生成的,页面不必花费昂贵的时间去服务器来呈现新页面。但很快SPA就变得很大,代码分裂成为一个问题。现在我们基本上回到服务器端渲染并将应用程序拆分成页面。这同样适用于GraphQL。有时查询太大,应该拆分。您可以拆分UserInfo
和ListOfFriends
的查询。在缓存中,字段将被合并。使用query batching,两个查询都将在同一请求中发送,并且一个GraphQL服务器可以正确实现每个请求资源缓存(例如,使用Dataloader)几乎不会发现差异。
也许你已经准备好使用订阅了。订阅从服务器发送已更改字段的更新。这样您就可以订阅用户的朋友并实时获取更新。好消息是Apollo Client,Relay和许多服务器实现已经为订阅提供支持。坏消息是它需要的websockets通常会对您的技术堆栈提出不同于纯HTTP的要求。
withApollo()
- > this.client.query
这应该只是你的最后手段!使用react-apollo的withApollo
高阶组件,您可以直接注入ApolloClient
实例。您现在可以使用this.client.query()
执行查询。 { user(id: 1) { friendlist { ... } } }
可用于获取好友列表并更新缓存,这将导致更新您的组件。这可能看起来像你想要的,但可能会在应用程序的后期阶段困扰你。