-
-
Notifications
You must be signed in to change notification settings - Fork 3k
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
fix(infiniteQuery): do not consume AbortSignal unless user has consumed it #3507
fix(infiniteQuery): do not consume AbortSignal unless user has consumed it #3507
Conversation
…ed it calling context.signal?.addEventListener did consume the signal
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/tanstack/react-query/8KTq9NWRqnH7uacZU4iAt3tLBHoz |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 0cec964:
|
…ed it fix formatting
@jcready I applied your patch here. There is one test failing:
so we now don't stop fetching once the component unmounts. This should happen independent of the AbortSignal. Any ideas? |
Hmmm. After looking at it for awhile I don't think there's a clean way to accomplish this w/o reverting part of #2996 such that (at least internally) the So either there needs to be some way for infinite query behavior to reset |
1 similar comment
Hmmm. After looking at it for awhile I don't think there's a clean way to accomplish this w/o reverting part of #2996 such that (at least internally) the So either there needs to be some way for infinite query behavior to reset |
I think I know what the problem is:
the important part is that always set in v4, we tried to do the same with Abort Signals. However, this lead to always consuming the signal, but it also made sure that we had now with this change, we only set I think the issue was partly there on v3 as well. because the promise always had a cancel function, we always reverted the state if the query unmounts instead of keeping fetching and putting the result into the queryCache, which is what we do with useQuery. This seems to be actually alright / wanted, because imagine we have 4 pages, and we re-fetch the first 2, then we unmount. What currently happens is that we revert the state, discarding the 2 refetched pages. What we could also do is continue to fetch all pages, and put them in the cache for later use. useQuery decides between the two cases by checking if the abort signal has been consumed. if yes, we also discard and revert. if no, we continue the fetch and put them in the cache for later use. So with an infinite query, what we cannot do is keep the first two fetched pages in the cache for later use and also stop fetching further pages, because that would give us a partially invalid state. What I'm trying to say is: It might actually be okay to treat infinite queries as "abort signal consumed", because we always want to revert to the previous state to avoid partially invalid states. That is, if we want to keep the behaviour from the test that says: |
@jcready the more I think about it, the more I think that your fix is actually correct, including the failing test. If the user doesn't consume the AbortSignal, and the component unmounts while it is fetching 5 pages from the infinite query - why should it stop? I could see the 5 fetches as "one batch", because it goes to the same cache entry. With a normal query, we also don't stop fetching, we just put the result in the cache. We only stop fetching if the AbortSignal is consumed. With infinite queries, it seems like we always "aborted" ongoing batches. 2 pages have been fetched, we don't fetch the other 3 - so we have to discard the result and revert back. If we want to keep this behaviour, we can close the PR. But it would at least mean that we'd need to document it here, because the current text is not true for infinite queries, as the data will not be available in the cache (also not in v3!):
If we want to change the behaviour to be in line with that documentation, I think we need to continue to fetch all pages, and then put them in the cache. I think your PR does this already, so we'd just need to change the existing test and maybe add a new one for infinite queries + abort signal. What do you think? |
@TkDodo I agree with that. Though I do think with some modification to the context it might also be possible to keep the "old" behavior. For example one relatively simply way to do this would be to pass the plain // query.ts
// Trigger behavior hook
const context: FetchContext<TQueryFnData, TError, TData, TQueryKey> = {
fetchOptions,
options: this.options,
queryKey: this.queryKey,
state: this.state,
fetchFn,
meta: this.meta,
cancellationSignal: abortController?.signal, // new
}
addSignalProperty(context)
this.options.behavior?.onFetch(context) This would then allow I'm happy with either outcome. |
I think we have the "old" behaviour right now on v4. The fetches get "cancelled" and that internal state is reverted. This has the (known) issue with react 18, strict effects in strict mode and query cancellation that you'll see two fetches, because react fires the subscription twice. This is not an issue without cancellation, because the fetches will just be deduped. |
hm, what I don't get is: If we don't revert the cache, but we keep the current behaviour and abort after 2 of 5 page fetches - how could that work / what state would the query be in? I think we have to either finish all the fetches and put them in the cache OR abort the fetches and revert. |
…nfinite-query-abort-signal
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
…nfinite-query-abort-signal
…nfinite-query-abort-signal
…nfinite-query-abort-signal
we want to continue fetching pages in the background even if the infinite query unmounts, unless the abort signal has been consumed. That is the documented behaviour, and also what useQuery is doing.
Codecov Report
@@ Coverage Diff @@
## beta #3507 +/- ##
=======================================
Coverage 97.11% 97.11%
=======================================
Files 49 49
Lines 2388 2392 +4
Branches 707 708 +1
=======================================
+ Hits 2319 2323 +4
Misses 67 67
Partials 2 2
Continue to review full report at Codecov.
|
I think the new behaviour is fine, as this is also what is documented (queries will just continue to fetch). If you want cancellation, you have to use the AbortSignal. Also, it fixes the reported issue, so I'm going to merge this. |
🎉 This PR is included in version 4.0.0-beta.16 🎉 The release is available on: Your semantic-release bot 📦🚀 |
fixes #3492