Skip to content

Conversation

@TkDodo
Copy link
Collaborator

@TkDodo TkDodo commented Oct 16, 2025

fixes #9727

Summary by CodeRabbit

  • Bug Fixes

    • Promise observation now implicitly observes associated data, fixing tracking and ensuring correct query results (including infinite queries).
  • New Features

    • Exported infinite-query hook made available from the public API.
  • Tests

    • Added tests verifying promise-driven observation correctly tracks data and renders pagination/loading states.
  • Chores

    • Added a changeset entry for a patch bump noting the observation fix.

@changeset-bot
Copy link

changeset-bot bot commented Oct 16, 2025

🦋 Changeset detected

Latest commit: e6fce97

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
@tanstack/query-core Patch
@tanstack/angular-query-experimental Patch
@tanstack/query-async-storage-persister Patch
@tanstack/query-broadcast-client-experimental Patch
@tanstack/query-persist-client-core Patch
@tanstack/query-sync-storage-persister Patch
@tanstack/react-query Patch
@tanstack/solid-query Patch
@tanstack/svelte-query Patch
@tanstack/vue-query Patch
@tanstack/angular-query-persist-client Patch
@tanstack/react-query-persist-client Patch
@tanstack/solid-query-persist-client Patch
@tanstack/svelte-query-persist-client Patch
@tanstack/react-query-devtools Patch
@tanstack/react-query-next-experimental Patch
@tanstack/solid-query-devtools Patch
@tanstack/svelte-query-devtools Patch
@tanstack/vue-query-devtools Patch

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

@TkDodo TkDodo marked this pull request as ready for review October 16, 2025 13:34
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 16, 2025

Walkthrough

Accessing a proxied query result's promise now also explicitly tracks data. A changeset was added documenting a patch bump for @tanstack/query-core. Tests were updated/added to assert implicit data observation when using the promise (including infinite-query hasNextPage scenarios).

Changes

Cohort / File(s) Summary
Changeset metadata
\.changeset/good-windows-tell.md``
New changeset entry documenting a patch bump for @tanstack/query-core and a fix note: "observing 'promise' needs to implicitly observe 'data'."
Query observer proxy tracking
packages/query-core/src/queryObserver.ts
Reorganized proxy get handler for promise: when promise is accessed it now explicitly tracks data in that branch and preserves the existing conditional rejection of a pending thenable when experimental_prefetchInRender is disabled.
Tests & public export usage
packages/react-query/src/__tests__/useQuery.promise.test.tsx
Added imports and tests verifying "should implicitly observe data when promise is used"; updated expectations and flows (including infinite-query hasNextPage) to reflect implicit data observation. Tests reference useInfiniteQuery (export surface used in tests).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Component as React component
  participant Proxy as QueryObserver Proxy
  participant Observer as QueryObserver internals
  participant Thenable as Query.thenable

  Component->>Proxy: access `query.promise` (e.g. use(query.promise))
  note right of Proxy #D6EAF8: proxy.get('promise') updated
  Proxy->>Observer: track('data')  ## explicit tracking added
  alt thenable pending and !experimental_prefetchInRender
    Observer->>Thenable: reject/throw pending thenable
    note right of Thenable #FDEBD0: triggers Suspense / error path
  else
    Observer->>Thenable: return thenable (normal path)
    note right of Thenable #E8F8F5: component can await/use data
  end
  Thenable-->>Component: resolved/rejected result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I tapped the promise, data stirred from its bed,
Now both wake together when use is said.
hasNextPage hums, no longer astray,
Suspense tips its hat and hops away. ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The description only contains “fixes #9727” and omits the required sections for “Changes”, “Checklist”, and “Release Impact” from the repository template, so it does not follow the prescribed structure or provide context about the change. Please expand the PR description to include the “🎯 Changes” section with details on what was modified and why, complete the “✅ Checklist” confirming contribution and testing steps, and fill out “🚀 Release Impact” to indicate changeset generation or dev-only impact.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly summarizes the primary change by indicating that observing the promise property will now implicitly observe data, matching the core fix implemented in the changeset and code. It is concise, specific to the main change, and follows conventional commit style without extraneous information.
Linked Issues Check ✅ Passed The code updates ensure that accessing promise now also tracks data and related properties, directly addressing the core issue of stale hasNextPage after suspension described in issue #9727. Tests were added and updated to verify implicit data observation via promise.
Out of Scope Changes Check ✅ Passed All modifications—including the changeset metadata, core logic in queryObserver.ts, and related tests—are focused on ensuring that observing promise implicitly observes data, which aligns with the linked issue objectives. No unrelated functionality or files appear to have been altered.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/fix/use-data

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Oct 16, 2025

View your CI Pipeline Execution ↗ for commit e6fce97

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 3m 13s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 28s View ↗

☁️ Nx Cloud last updated this comment at 2025-10-16 14:23:13 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 16, 2025

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@9772

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@9772

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@9772

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@9772

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@9772

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@9772

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@9772

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@9772

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@9772

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@9772

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@9772

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@9772

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@9772

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@9772

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@9772

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@9772

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@9772

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@9772

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@9772

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@9772

commit: e6fce97

@github-actions
Copy link
Contributor

github-actions bot commented Oct 16, 2025

Sizes for commit e6fce97:

Branch Bundle Size
Main
This PR

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 (1)
packages/react-query/src/__tests__/useQuery.promise.test.tsx (1)

1388-1433: Well-crafted test that validates the fix for issue #9727.

The test correctly verifies that accessing query.promise via React.use() now implicitly tracks data, ensuring that hasNextPage (which depends on the tracked data) reflects the correct value after suspending. The query setup, suspense handling, and assertions are all appropriate.

Optional suggestions for enhanced clarity:

  • Consider adding a brief inline comment before line 1405 explaining that this test specifically validates implicit data observation when using the promise (e.g., // Accessing promise should implicitly track data, ensuring hasNextPage is correctly computed).
  • For completeness, you could add a complementary test case that verifies hasNextPage: false when getNextPageParam returns null or undefined.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a72df8 and a7e6603.

📒 Files selected for processing (1)
  • packages/react-query/src/__tests__/useQuery.promise.test.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/react-query/src/__tests__/useQuery.promise.test.tsx (2)
packages/query-core/src/queryObserver.ts (1)
  • query (704-721)
packages/query-core/src/infiniteQueryBehavior.ts (1)
  • hasNextPage (162-168)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test

@codecov
Copy link

codecov bot commented Oct 16, 2025

Codecov Report

❌ Patch coverage is 16.66667% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.77%. Comparing base (64507ba) to head (e6fce97).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #9772       +/-   ##
===========================================
+ Coverage   45.75%   59.77%   +14.02%     
===========================================
  Files         200      129       -71     
  Lines        8403     5619     -2784     
  Branches     1930     1537      -393     
===========================================
- Hits         3845     3359      -486     
+ Misses       4111     1955     -2156     
+ Partials      447      305      -142     
Components Coverage Δ
@tanstack/angular-query-experimental 93.85% <ø> (ø)
@tanstack/eslint-plugin-query ∅ <ø> (∅)
@tanstack/query-async-storage-persister 43.85% <ø> (ø)
@tanstack/query-broadcast-client-experimental 24.39% <ø> (ø)
@tanstack/query-codemods ∅ <ø> (∅)
@tanstack/query-core 97.37% <16.66%> (-0.12%) ⬇️
@tanstack/query-devtools 3.48% <ø> (ø)
@tanstack/query-persist-client-core 80.00% <ø> (ø)
@tanstack/query-sync-storage-persister 84.61% <ø> (ø)
@tanstack/query-test-utils ∅ <ø> (∅)
@tanstack/react-query 96.01% <ø> (ø)
@tanstack/react-query-devtools 10.00% <ø> (ø)
@tanstack/react-query-next-experimental ∅ <ø> (∅)
@tanstack/react-query-persist-client 100.00% <ø> (ø)
@tanstack/solid-query 78.06% <ø> (ø)
@tanstack/solid-query-devtools 61.90% <ø> (ø)
@tanstack/solid-query-persist-client 100.00% <ø> (ø)
@tanstack/svelte-query ∅ <ø> (∅)
@tanstack/svelte-query-devtools ∅ <ø> (∅)
@tanstack/svelte-query-persist-client ∅ <ø> (∅)
@tanstack/vue-query 71.10% <ø> (ø)
@tanstack/vue-query-devtools ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 (2)
packages/react-query/src/__tests__/useQuery.promise.test.tsx (2)

420-423: Brittle renderedComponents ordering assertions

Adjustments to expect(renderedComponents).toEqual([Page, MyComponent]) look correct functionally, but strict array equality on render order can be flaky across React versions/runtimes. Consider relaxing:

  • Assert presence instead of exact order: expect(renderedComponents).toEqual(expect.arrayContaining([Page, MyComponent])) and assert length
  • Or assert DOM output only (already done in most tests)

Also applies to: 488-491, 682-685, 1097-1100, 1111-1114


1287-1294: Make background-update assertion deterministic under fake timers

The new waitFor is reasonable, but with vi.useFakeTimers shouldAdvanceTime: true, polling can still be timing-sensitive. Prefer explicit timer advancement + stream take to reduce flakiness.

Apply this diff:

-    {
-      const { snapshot } = await renderStream.takeRender()
-      expect(snapshot).toMatchObject({ data: 'test3' })
-    }
+    {
+      const { snapshot } = await renderStream.takeRender()
+      expect(snapshot).toMatchObject({ data: 'test3' })
+    }

-    await waitFor(() => rendered.getByText('test0new'))
+    await vi.advanceTimersByTimeAsync(10)
+    {
+      const { withinDOM } = await renderStream.takeRender()
+      withinDOM().getByText('test0new')
+    }

If you prefer keeping waitFor, consider jest/rtl timer config to ensure it integrates with vitest fake timers in CI.

Also applies to: 1302-1303

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7e6603 and e6fce97.

📒 Files selected for processing (1)
  • packages/react-query/src/__tests__/useQuery.promise.test.tsx (9 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/react-query/src/__tests__/useQuery.promise.test.tsx (2)
packages/query-core/src/queryObserver.ts (1)
  • query (704-721)
packages/query-core/src/infiniteQueryBehavior.ts (1)
  • hasNextPage (162-168)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test
🔇 Additional comments (3)
packages/react-query/src/__tests__/useQuery.promise.test.tsx (3)

9-9: Confirm peer dependency for waitFor

Using waitFor from @testing-library/react 16.x requires @testing-library/dom as a peer. Ensure it’s installed to avoid runtime/typings issues in CI.

Based on learnings


15-17: Public export of useInfiniteQuery

Importing useInfiniteQuery from the package barrel implies it’s exported publicly. Please confirm the export is present in the public module to keep tests (and consumers) aligned.


1385-1430: Great coverage: implicit data observation via promise

This precisely captures the regression for infinite queries (hasNextPage becomes true after suspension). LGTM.

@TkDodo TkDodo merged commit e42ddfe into main Oct 16, 2025
8 of 9 checks passed
@TkDodo TkDodo deleted the feature/fix/use-data branch October 16, 2025 15:07
@github-actions github-actions bot mentioned this pull request Oct 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unexpected behaviour involving tracked properties and React's use function

1 participant