Skip to content

Conversation

0xdiid
Copy link

@0xdiid 0xdiid commented Oct 10, 2025

🎯 Changes

This introduces a check when updating dataUpdateCount so that it isn't updated when setting initial data. This in turn fixes the isFetchedAfterMount bug discussed in #9656

fixes #9656

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm test:pr

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • Bug Fixes

    • Corrected isFetchedAfterMount when initial data is present at mount; initial data no longer increments update counters.
    • Subsequent observer-initiated refetches correctly update data and counters.
  • Tests

    • Added tests validating initial-data behavior, data update counts, and isFetchedAfterMount transitions.
  • Chores

    • Added a patch changeset entry reflecting the fix.

Copy link

changeset-bot bot commented Oct 10, 2025

🦋 Changeset detected

Latest commit: 478f5d0

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

This PR includes changesets to release 4 packages
Name Type
@tanstack/react-query Patch
@tanstack/react-query-devtools Patch
@tanstack/react-query-next-experimental Patch
@tanstack/react-query-persist-client 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

Copy link
Contributor

coderabbitai bot commented Oct 10, 2025

Walkthrough

Fix query success handling so observer-provided initialData (manual) does not increment dataUpdateCount, add a test reproducing isFetchedAfterMount behavior, and include a changeset marking a patch for @tanstack/react-query.

Changes

Cohort / File(s) Summary
Core logic update
packages/query-core/src/query.ts
Modify Success action: when action.manual is true and previous state.data is undefined (initial manual data), do not increment dataUpdateCount; otherwise increment as before. Preserve dataUpdatedAt; #revertState handling remains guarded by action.manual.
Tests
packages/query-core/src/__tests__/query.test.tsx
Add test ensuring an observer mounting with initialData does not increment dataUpdateCount and isFetchedAfterMount stays false until an observer-initiated refetch updates data and increments the counter.
Changeset
.changeset/yummy-rooms-read.md
Add patch changeset for @tanstack/react-query documenting the bugfix for isFetchedAfterMount when initialData is applied at mount.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor UI as Component
  participant Obs as QueryObserver
  participant QC as QueryClient
  participant Q as Query

  UI->>Obs: Mount with initialData
  Obs->>QC: Subscribe to query key
  QC->>Q: Create/attach observer
  Note right of Q #d6f5d6: Apply initialData as manual\n(no dataUpdateCount increment,\nisFetchedAfterMount=false)

  UI->>Obs: Trigger refetch
  Obs->>Q: fetch()
  Q->>Q: Resolve to fetched data
  Note right of Q #f5e6d6: Update data, increment dataUpdateCount\nisFetchedAfterMount=true
  Q-->>Obs: Notify result
  Obs-->>UI: Render with fetched data
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • TkDodo

Poem

A hop, a patch, a careful tweak,
I guard the counts when data's meek. 🥕
Initial nibbles leave no drum,
But fetch-time thumps now loudly come.
I twitch my nose and bound with glee.

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The title concisely and accurately summarizes the primary change by specifying that dataUpdateCount will no longer be updated when setting initial data, which matches the core fix in the changeset.
Linked Issues Check ✅ Passed The implementation and accompanying test directly address issue #9656 by preventing dataUpdateCount from incrementing on initial data, restoring correct isFetchedAfterMount behavior, preserving prefetch behavior, and including a minimal test that validates the fix.
Out of Scope Changes Check ✅ Passed All modifications are focused on the conditional update of dataUpdateCount in the query reducer, the corresponding test, and the changeset entry, with no unrelated files or features affected.
Description Check ✅ Passed The pull request description follows the required template by providing the Changes, Checklist, and Release Impact sections fully populated, clearly explaining the motivation and linking the issue, confirming guideline compliance and testing, and noting the added changeset.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad5d0ba and 478f5d0.

📒 Files selected for processing (1)
  • packages/query-core/src/query.ts (1 hunks)
🔇 Additional comments (1)
packages/query-core/src/query.ts (1)

639-642: LGTM! Fix correctly prevents dataUpdateCount increment for initial data.

The conditional logic properly addresses the regression where setting initialData via setData with manual: true incorrectly incremented dataUpdateCount. The condition action.manual && state.data === undefined correctly identifies the first-time manual data set scenario (initial data application) and preserves dataUpdateCount at 0, ensuring isFetchedAfterMount only becomes true after an actual fetch.

The implementation handles subsequent cases correctly:

  • Subsequent manual updates (when state.data !== undefined) increment normally
  • All fetch-based updates increment normally
  • The logic aligns with the existing #revertState handling for manual updates

Edge case note: If data is manually cleared (set to undefined) and then set again manually, the second set won't increment dataUpdateCount because state.data === undefined again. This is acceptable because such scenarios are rare and don't materially affect isFetchedAfterMount semantics in practice.


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.

❤️ Share

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

Copy link

nx-cloud bot commented Oct 12, 2025

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 478f5d0

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ❌ Failed 4m 49s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 18s View ↗

☁️ Nx Cloud last updated this comment at 2025-10-12 15:57:37 UTC

Comment on lines 639 to 641
dataUpdateCount: action.manual && state.data === undefined
? state.dataUpdateCount // Don't increment for initial data
: state.dataUpdateCount + 1,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m surprised that this doesn’t break any existing tests. For example, we would still want the count to increase if you call queryClient.setQueryData() manually while e.g. a prefetch is in-flight. The exception should likely only be for initialData

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it did fail on CI, not sure why locally it didn't run those tests. I'll mess with it today as work allows (although this is blocking us from another fix so I'd like to tackle it asap)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the fix should not change code here, but instead dispatch setState directly with the state we want for initialData rather than calling setData

Copy link

pkg-pr-new bot commented Oct 12, 2025

More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: 478f5d0

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.

isFetchedAfterMount was broken in commit 1c8a921 / v5.87.1

2 participants