-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Don't cancel fetchQuery when unmounting useQuery #9799
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
base: main
Are you sure you want to change the base?
Don't cancel fetchQuery when unmounting useQuery #9799
Conversation
🦋 Changeset detectedLatest commit: ebe1535 The changes in this PR will be included in the next version bump. This PR includes changesets to release 19 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughThe PR modifies query cancellation semantics in TanStack Query. When Changes
Sequence DiagramsequenceDiagram
participant Client as queryClient.fetchQuery
participant Observer as QueryObserver
participant Query as Query
participant Cache as Cache
Client->>Client: Check if data is stale
alt Data is stale
Client->>Observer: Create and attach observer
Observer->>Query: Subscribe to query
Client->>Query: Execute fetch
Query->>Cache: Update data
Client->>Observer: Remove observer (finally)
Note over Client,Cache: Query remains in cache<br/>not cancelled by other<br/>observer unsubscribes
else Data is fresh
Client->>Cache: Return cached data
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes The changes introduce logic modifications to fetchQuery's control flow with observer lifecycle management, span multiple test files with varying adjustments, and require understanding interactions between QueryObserver and cancellation semantics. Changes are moderately heterogeneous across implementation and tests. Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
.changeset/petite-towns-rule.md (1)
5-5: Tighten wording and format the API name.Suggest: “When running
queryClient.fetchQuery, the query will no longer be cancelled if other observers unsubscribe.” This adds code formatting, active voice, and the more common “unsubscribe.”packages/query-core/src/queryClient.ts (1)
366-379: Using a temporary QueryObserver to prevent cancellation is sound; add small polish.
- Behavior change is correct: keeping one observer prevents “last-unsubscribe” cancellation while
fetchQueryis in flight. LGTM.- Minor: adding the observer via
query.addObserver(observer)(without listeners) can still emit cache notifications fromobserver.updateResult(); acceptable, but worth noting for large subscriber counts.- Optional polish: keep style consistent and use a clearer try/finally.
- const isDataStale = query.isStaleByTime( - resolveStaleTime(defaultedOptions.staleTime, query), - ); + const isDataStale = query.isStaleByTime( + resolveStaleTime(defaultedOptions.staleTime, query), + ) @@ - const observer = new QueryObserver(this,defaultedOptions) - query.addObserver(observer); - - return query.fetch(defaultedOptions).finally(() => query.removeObserver(observer)) + const observer = new QueryObserver(this, defaultedOptions) + query.addObserver(observer) + try { + return await query.fetch(defaultedOptions) + } finally { + query.removeObserver(observer) + }Please double‑check that this path preserves existing pause/resume semantics (offline/focus) by running the affected tests for paused retries and onFocus/onOnline refetch.
packages/query-core/src/__tests__/query.test.tsx (1)
294-305: Timer alignment nit.The added 10ms advance before unsubscribe makes the race explicit. Consider adding a brief inline comment “start fetch → unsubscribe after 10ms” for clarity.
packages/react-query/src/__tests__/useQuery.test.tsx (1)
6780-6845: Solid coverage for “don’t cancel fetchQuery on unmount”; fix comment.The test correctly asserts that the AbortSignal remains un‑aborted and
fetchQueryresolves. Minor nit: comment says “after 2 seconds” but timers use ~10–11ms; update the comment to avoid confusion.- // This unmounts useQuery after 2 seconds, fetchQuery should continue running + // This unmounts useQuery after ~10ms; fetchQuery should continue running
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.changeset/petite-towns-rule.md(1 hunks)packages/query-core/src/__tests__/query.test.tsx(3 hunks)packages/query-core/src/queryClient.ts(2 hunks)packages/react-query/src/__tests__/useQuery.test.tsx(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
packages/react-query/src/__tests__/useQuery.test.tsx (3)
packages/react-query/src/queryOptions.ts (1)
queryOptions(85-87)packages/query-core/src/utils.ts (1)
sleep(363-367)packages/react-query/src/__tests__/utils.tsx (1)
renderWithClient(9-23)
packages/query-core/src/__tests__/query.test.tsx (1)
packages/query-core/src/utils.ts (1)
sleep(363-367)
packages/query-core/src/queryClient.ts (3)
packages/query-core/src/queryObserver.ts (2)
query(704-721)QueryObserver(41-747)packages/query-core/src/utils.ts (1)
resolveStaleTime(101-113)packages/query-core/src/queriesObserver.ts (1)
observer(263-269)
🔇 Additional comments (3)
packages/query-core/src/queryClient.ts (1)
16-16: Import looks correct and scoped to core.
No concerns.packages/query-core/src/__tests__/query.test.tsx (1)
216-238: Good AbortSignal consumption check.Adding
signal.throwIfAborted()and asserting resolved data validates the new non‑cancellation behavior offetchQuery.packages/react-query/src/__tests__/useQuery.test.tsx (1)
16-16: queryOptions export confirmed
packages/react-query/src/index.tsline 20 re-exportsqueryOptions— no further action needed.
🎯 Changes
This is an attempt to solve issue #9798.
It adds an query observer when running
fetchQuery, to make sure the query is not cancelled if all other observers are unsubscribed.I am unfamiliar with this codebase, and at least one test is still failing. I am unsure if this is the right direction to fix the issue. If anyone wants to take over this PR, feel free to do so.
✅ Checklist
pnpm run test:pr.🚀 Release Impact
Summary by CodeRabbit
fetchQuerywould cancel in-progress queries when other observers unsubscribed. Queries now continue to completion as expected.