阿波罗客户端。为什么第二次使用未修改的缓存调用突变“更新”回调?

问题描述 投票:0回答:1

我正在尝试使用

cache.modify
来更新突变后的字段。这是我的
reactions
模型的
Message
字段。该突变消除了
reactions
场的反应。我正在使用乐观的反应。

奇怪的是,当获得后端响应第二次触发时,

update
会以未修改的缓存被调用。

这是一个小代码示例(

removeReactionMutation
useMutation
钩子返回的突变函数):

   const { data } = await removeReactionMutation({
                    variables,
                    optimisticResponse,
                    update: ((cache, options) => {
                            const { data } = options;
                            console.log('update called', options);
                            console.log(
                                'optimistic cache',
                                JSON.stringify(
                                    cache.extract(true)[GUID2ACID(variables.messageId)].reactions
                                )
                            );
                            console.log(
                                'real cache',
                                JSON.stringify(
                                    cache.extract()[GUID2ACID(variables.messageId)].reactions
                                )
                            );

                            cache.modify({
                                id: GUID2ACID(variables.messageId),
                                fields: {
                                    reactions(existing) {
                                        console.log('removing reaction', {
                                            existing,
                                            userId: identity.guid,
                                            emojiId: variables.emojiId,
                                        });
                                        return existing.filter(
                                            (reaction: IAPIMessageReaction) =>
                                                reaction.userId !== identity.guid ||
                                                reaction.emojiId !== variables.emojiId
                                        );
                                    },
                                },
                                optimistic: true, // this flag seems to have no effect 
                            });

                            console.log(
                                'optimistic cache',
                                JSON.stringify(
                                    cache.extract(true)[GUID2ACID(variables.messageId)].reactions
                                )
                            );
                            console.log(
                                'real cache',
                                JSON.stringify(
                                    cache.extract()[GUID2ACID(variables.messageId)].reactions
                                )
                            );
                        }),
                });

这是

console.log
输出:

useEmojis.ts:163 update called {data: {…}} <----- called with optimistic response
useEmojis.ts:164 optimistic cache [... 5 records]
useEmojis.ts:170 real cache [...5 records]
useEmojis.ts:195 removing reaction {existing: Array(5), userId: '...', emojiId: '...'}
useEmojis.ts:210 optimistic cache [...4 records]
useEmojis.ts:216 real cache [...4 records]
useEmojis.ts:163 update called {data: {…}} <----- called with backend response
useEmojis.ts:164 optimistic cache [... 5 records] <----- WHY!?
useEmojis.ts:170 real cache [... 5 records] <----- WHY!?
useEmojis.ts:195 removing reaction {existing: Array(5), userId: '...', emojiId: '...'}
useEmojis.ts:210 optimistic cache [... 4 records]
useEmojis.ts:216 real cache [... 4 records]

因此,在第一次

update
调用期间,该项目被
cache.modify
(乐观层和主层)从缓存中删除。 UI 已正确更新,并且反应已消除。到目前为止一切顺利!

但是,该项目仍然存在于缓存中,并且在获得服务器响应后第二次调用

existing
回调时的
update
值!

这非常令人困惑并且会导致问题。

如果

update
被快速调用多次,然后随着服务器响应一一传入,又被多次调用,过时的缓存和
existing
值会导致已删除的项目暂时重新出现在在它们最终被删除之前的 UI。

这是因为您有两个待处理的

cache.modify
电话。两个调用都会删除自己的项目,但由于第一个调用获取现有值,而另一个项目错误地出现在数组中,因此该项目将在第一个
cache.modify
调用后在 UI 中重新出现一段时间。第一次调用不会删除它(这是预期的),并且另一个项目会显示,直到第二次调用最终删除它。我希望这是有道理的。

所以最后你需要一些外部逻辑来保存所有应该删除的项目并过滤

existing
,以便所有要删除的项目都从
existing
值中排除。需要有这样的外部逻辑感觉不太对。

另外,我尝试使用

cache.modify
标志打开/关闭来调用
optimistic
,但在任何一种情况下,两个缓存层都被修改,因此不清楚该标志的含义。

我的问题是为什么在

update
回调的第二次调用期间,缓存再次在两层中保存已删除的项目?

换句话说,缓存在第二次

update
调用期间处于未修改状态,这不是 UI atm 中呈现的内容。这是我无法理解的事情,我很感激这里的任何帮助或想法。

apollo-client react-apollo
1个回答
0
投票

好吧,我明白了...

这并不神秘,缓存会因为实时订阅而更新。所以它发生在突变

update
回调之外。在回调运行之间,由于实时订阅消息的传入,缓存会被修改。

我将为可能遇到类似问题的任何人保留这个答案。您很可能需要寻找其他可以更新缓存的地方。

© www.soinside.com 2019 - 2024. All rights reserved.