Graphql 更新用作全局存储的Apollo缓存时,如何分离逻辑?
使用Apollo缓存作为全局存储—用于远程和本地数据,非常方便 然而,虽然我从未使用过redux,但我认为它最重要的是实现flux:前端的事件驱动架构可以分离逻辑并确保关注点的分离 我不知道如何用阿波罗实现这一点。医生说 当变异修改多个实体时,或者如果它创建或删除实体,Apollo客户端缓存不会自动更新以反映变异的结果。要解决这个问题,对UseMotation的调用可以包括一个更新函数 在处理所有缓存更新的应用程序的一个部分中添加一个Graphql 更新用作全局存储的Apollo缓存时,如何分离逻辑?,graphql,react-apollo,apollo-client,flux,Graphql,React Apollo,Apollo Client,Flux,使用Apollo缓存作为全局存储—用于远程和本地数据,非常方便 然而,虽然我从未使用过redux,但我认为它最重要的是实现flux:前端的事件驱动架构可以分离逻辑并确保关注点的分离 我不知道如何用阿波罗实现这一点。医生说 当变异修改多个实体时,或者如果它创建或删除实体,Apollo客户端缓存不会自动更新以反映变异的结果。要解决这个问题,对UseMotation的调用可以包括一个更新函数 在处理所有缓存更新的应用程序的一个部分中添加一个update函数;通过更新应用程序所有其他部分的查询和/或片段
update
函数;通过更新应用程序所有其他部分的查询和/或片段,这正是我们希望在Flux事件驱动体系结构中避免的
为了说明这一点,让我举一个简单的例子。这里,我们有(至少3个链接组件)
1。收件箱计数
显示SideNav中收件箱项目数的组件
query getInboxCount {
inbox {
id
count
}
}
2。收件箱列表项目
在收件箱页面中显示项目的组件
query getInbox {
inbox {
id
items {
...ItemPreview
...ItemDetail
}
}
}
这两个组件都从自动生成的钩子读取GQL查询中的数据,即.const{data,load}=useGetInboxItemsQuery()
3。附加项
创建新项的组件。因为它创建了一个新的实体,我需要手动更新缓存。所以我不得不写
(伪代码)
const[addItem,{loading}]=useCreateItem({
更新(缓存,{data}){
const cachedData=cache.readQuery({
查询:GetInboxItemsDocument,
})
如果(缓存数据?.inbox){
//1.更新项目列表GetInboxItemsQuery
const newItems=cachedData.inbox.items.concat(data.items)
cache.writeQuery({
查询:GetInboxItemsDocument,
数据:{
收件箱:{
id:'我',
__typename:“收件箱”,
项目:新项目,
},
},
})
//2.更新另一个封装到另一个可重用方法中的查询,如下所示
setInboxCount(缓存,newItems.length)
}
},
})
在这里,我的AddItem
组件必须知道我在应用程序中声明的不同的其他查询/片段关于update
的不幸事实是,它以简单性换取性能。真正的“哑”客户机只会从服务器接收数据并进行渲染,而不会对其进行操作。通过指示Apollo在发生变异后如何修改缓存,我们不可避免地复制了服务器上已经存在的业务逻辑。避免这种情况的唯一方法是:
- 让变异返回图的较大部分。例如,如果用户创建帖子,则返回完整的用户对象,包括用户的所有帖子,而不是返回创建的帖子
- 重新提取受影响的查询
当然,通常这两种方法都不是特别可取的,我们选择将业务逻辑注入到客户端应用程序中
分离此业务逻辑可能非常简单,只需将更新函数保存在一个单独的文件中,然后根据需要导入它们即可。这样,至少可以单独测试更新逻辑。您也可能更喜欢更优雅的解决方案,如利用链接。是一个很好的链接示例,它允许您将update
逻辑与组件分离。它还解决了必须跟踪查询变量才能执行这些更新的问题。实际上,您应该对两个位置使用count
属性(如果不需要重新查询,则需要一个写缓存)-收件箱(所有空间/位置)应该分页,并使用“显示更多”或使用虚拟化列表呈现
const [addItem, { loading }] = useCreateItemMutation({
update(cache, { data }) {
const cachedData = cache.readQuery<GetInboxItemsQuery>({
query: GetInboxItemsDocument,
})
if (cachedData?.inbox) {
// 1. Update items list GetInboxItemsQuery
const newItems = cachedData.inbox.items.concat(data.items)
cache.writeQuery({
query: GetInboxItemsDocument,
data: {
inbox: {
id: 'me',
__typename: 'Inbox',
items: newItems,
},
},
})
// 2. Update another query wrapped into another reusable method, here
setInboxCount(cache, newItems.length)
}
},
})