如何深度更新嵌套的Apollo Cache 3+级别



我有一个NuxtJS应用程序,在我的Apollo缓存中有深度嵌套的数据。举个例子,我的缓存可能是这样的,Trips有很多Categories,其中有很多Items。

ROOT_QUERY
trips: [Trip]
0: Trip:1
categories: [Category]
0: Category:1
items: [Item]
0: Item:1
1: Item:2
2: Item:3  
1: Trip:2

在将项目删除或添加到位于trips[0].categories[0]中的项目数组后,我正在尝试更新缓存。我所做的是有效的,但只有在它与我的服务器对话并返回响应时,似乎有1-2秒的延迟之后。在我看来,optimisticResponse要么工作不正常,要么数据嵌套太深,无法足够快地更新UI。

以下是我的removeItem函数:

import { remove } from 'lodash';
async function removeItem ({ fields, trip_id, apollo }) {
return await apollo.mutate({
mutation: removeItemMutation,
variables: fields,
optimisticResponse: {
__typename: 'Mutation',
removeItem: {
__typename: 'item',
id: fields.item_id,
name: '',
weight: 0,
unit: '',
price: 0,
category_id: fields.category_id,
quantity: 0,
position: 0,
created_at: Date.now(),
updated_at: Date.now()
}
},
update: (cache, { data: { removeItem } }) => {
console.log({ removeItem });
// read
const data = cache.readQuery({ query: tripsQuery });
// mutate
const trip = data.trips.find(trip => trip.id === trip_id);
const category = trip.categories.find(category => category.id === removeItem.category_id);
remove(category.items, item => item.id === removeItem.id);
const otherTrips = data.trips.filter(t => t.id !== trip_id);
// write
cache.writeQuery({
query: tripsQuery,
data: {
trips: [trip, ...otherTrips]
}
});
}
});
}

我可以在更新功能日志中看到console.log两次,所以我知道optimisticResponse至少在触发它,我只是不确定为什么更新UI看起来这么慢?有更好的方法来处理这个问题吗?

更新:

我想我已经把它缩小到store.writeQuery()函数了。我将我的网络速度设置为";慢速3G";,在整个更新函数中添加了一堆控制台日志,它们几乎都是即时的,这使得writeQuery函数成为罪魁祸首。在这一点上,我真的不确定改变Apollo缓存中嵌套数据的最有效方法是什么,我已经仔细研究了好几天的文档。

更新2:

我做了一个有趣的实验,在最初的大型Trips查询之后运行Categories查询。据我所知,它将避免发出第二次请求,因为缓存中已经存在该数据,而这同样有效的作用是将我的缓存更改为如下所示:

ROOT_QUERY
trips: [Trip]
0: Trip:1
categories: [Category]
0: Category:1
items: [Item]
0: Item:1
1: Item:2
2: Item:3  
1: Trip:2
categories: [Category]
0: Category:1
items: [Item]
0: Item:1
1: Item:2
2: Item:3  
1: Category:2
2: Category:3
3: Category:4
...

这有效地将Categories和Trips都放在了ROOT_QUERY的顶层,当我修改服务函数以写入Categories时,它将时间从~2.5s减少到~350ms。

我认为这非常清楚地表明,数据嵌套甚至像最初的Items一样深3层,这就是导致问题的原因。我现在唯一的问题是,如果第一次不完全按照需要返回数据,那么使用GraphQL/Apolo有什么意义?为什么我必须运行多个查询来伪展平缓存?

尝试@apollo/client提供的cache.modify()(链接到api(>v3。流程简单:

  1. 识别要修改的对象
  2. 指定要修改的字段(包括嵌套字段(
client.cache.modify({
id: client.cache.identify({ __typename: 'OBJ_TYPE_NAME', id: <OBJ_IDENTIFIER> }),
fields: {
myField(currentValueOFMyField) {
return { ...currentValueOFMyField, myNestedField: 'new val' };
},
},
});

希望这能帮助到别人。

最新更新