-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unmounting a component in the middle of refetching queries will result in cache not getting updated properly #8274
Comments
Thanks for the detailed analysis @dannycochran! After some digging into the Git history: #7278 was the PR where In the longer term (AC4), these |
@benjamn thanks for the response, #7661 makes sense and it seems like we'd want to preserve that behavior to prevent the original garbage collection bug. Do you remember where that bug was happening? I'm wondering if we can just allow a bypass of some sort from useEffect(() = () => {
return () => queryData.cleanup({ allowPendingCacheWrite: true });
}, []); and then: stopped = false;
allowPendingCacheWrite = false;
public markResult(...) {
const shouldWriteToCache = (!this.stopped || this.allowPendingCacheWrite) && allowCacheWrite;
if (options.fetchPolicy === 'no-cache') {
this.diff = { result: result.data, complete: true };
} else if (shouldWriteToCache) {
/* ... */
}
}
public stop(options?: StopOptions) {
if (!this.stopped) {
this.stopped = true;
this.allowPendingCacheWrite = options?.allowPendingCacheWrite ?? false;
/* ... */
}
} |
@dannycochran See my comments here #8440. I can’t get reliably reproduce the race condition in the test suite, so I’m unsure how to proceed. Sorry! |
@brainkim I think to reproduce you just need to:
edit: here's a reproduction repository: |
Intended outcome:
A mutation with refetchQueries should properly update the cache upon refetchQueries network requests successfully completing, even if the underlying component housing the query is unmounted for whatever reason.
For instance:
In this scenario, the refetch queries fire and actually complete. However, in between the time that
refetchQueries
has completed and the cache write occurs, the component housing the query unmounts. This triggers a series of events:The query cleanup is called here when unmounting: https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/utils/useBaseQuery.ts#L74
This calls
removeQuerySubscription
This calls a number of other functions before finally calling
queryInfo.stop()
Elsewhere, the query is now ready to write to cache and hits this block of code, but because
this.stopped
is now true, it will skip the cache write.IMO I think the usage of
this.stopped
to gate the cache write does not make sense. Even if a query is unmounted or gone, any results coming in tomarkResult
can still be updated with valid data, but just skip broadcasting any queries like it's already doing here.Actual outcome:
The cache write is skipped because the component housing the query has unmounted in between the time the refetchQueries have completed and the
markReady
function is called.How to reproduce the issue:
It's tricky to reproduce but the code snippet above illustrates how to get into the race condition.
Versions
The text was updated successfully, but these errors were encountered: