Skip to content

Conversation

@HuijungYoon
Copy link

@HuijungYoon HuijungYoon commented Dec 15, 2025

fixes #9787

fix(query-core): prevent reducer from being called twice in streamedQuery #9787

  • Fix bug where reducer was called twice for each chunk (once in setQueryData, once in loop)
  • Store reducer result in variable to avoid duplicate calls
  • Add test case to verify reducer is only called once per chunk

🎯 Changes

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run 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

    • Fixed an issue where streamed data could be applied twice during a refetch using "replace" mode; stream items are now applied once and the displayed data remains stable during and after refetch.
  • Tests

    • Added a test verifying streamed refetch behavior to ensure stream updates are applied a single time and overall data consistency is preserved.

✏️ Tip: You can customize this high-level summary in your review settings.

…uery TanStack#9787

- Fix bug where reducer was called twice for each chunk (once in setQueryData, once in loop)
- Store reducer result in variable to avoid duplicate calls
- Add test case to verify reducer is only called once per chunk
@changeset-bot
Copy link

changeset-bot bot commented Dec 15, 2025

🦋 Changeset detected

Latest commit: ee74b57

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

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 15, 2025

Warning

Rate limit exceeded

@TkDodo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 55 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between ad98335 and ee74b57.

📒 Files selected for processing (2)
  • packages/query-core/src/__tests__/streamedQuery.test.tsx
  • packages/query-core/src/streamedQuery.ts
📝 Walkthrough

Walkthrough

Updated streamedQuery per-chunk handling to precompute the next reduced value, preventing duplicate reducer invocations; added a test that verifies the reducer is not called twice when refetchMode is "replace", and added a changeset entry documenting the fix.

Changes

Cohort / File(s) Change Summary
Streamed Query Test
packages/query-core/src/__tests__/streamedQuery.test.tsx
Added test "should not call reducer twice when refetchMode is replace" that asserts reducer invocation counts and observable data before and after a refetch with replace mode.
Streamed Query Implementation
packages/query-core/src/streamedQuery.ts
Changed per-chunk processing to compute nextResult = reducer(result, chunk), pass nextResult into setQueryData, then assign result = nextResult to avoid calling the reducer twice.
Changeset
.changeset/fair-peaches-deny.md
Added a changeset documenting a bug fix release entry for @tanstack/query-core: "Fix streamedQuery reducer being called twice".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay extra attention to:
    • streamedQuery.ts per-chunk path where nextResult is computed and passed into setQueryData.
    • streamedQuery.test.tsx timing (timer advances) and assertions on reducer call counts and observable data.
    • Assumptions about reducer purity or in-place mutation that could be affected by precomputing results.

Possibly related PRs

Suggested reviewers

  • TkDodo
  • manudeli

Poem

🐇 I hopped through streams of ones and twos,
Collected chunks without repeat blues.
nextResult saved a double call,
Now reducers dance just once—no fall.
🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title accurately describes the main bug fix: preventing the reducer from being called twice in streamedQuery, which is the primary change in this PR.
Description check ✅ Passed The PR description provides clear context about the bug fix, includes specific issue reference (#9787), explains the changes made, and all checklist items are properly completed.

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
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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f15b7fc and bc8d7be.

📒 Files selected for processing (2)
  • packages/query-core/src/__tests__/streamedQuery.test.tsx (1 hunks)
  • packages/query-core/src/streamedQuery.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.
📚 Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Applied to files:

  • packages/query-core/src/__tests__/streamedQuery.test.tsx
🧬 Code graph analysis (1)
packages/query-core/src/__tests__/streamedQuery.test.tsx (1)
packages/query-core/src/streamedQuery.ts (1)
  • streamedQuery (46-97)

Fixed an issue where the reducer was being invoked twice when refetchMode is set to 'replace'.
Added a regression test to verify the fix.

Fixes TanStack#9787
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/query-core/src/__tests__/streamedQuery.test.tsx (1)

501-536: Past review feedback has been addressed correctly.

The test now properly verifies that the reducer is called exactly once per chunk:

  • Line 525 correctly expects [1, 2, 3] after the initial fetch
  • Line 532 correctly expects [1, 2, 3, 1, 2, 3] after refetch
  • The console.log statement has been removed

The test logic is sound and will catch regressions if the double-call bug reappears.

Minor: Extra whitespace in array literal.

Line 525 has trailing whitespace before the closing bracket: [1, 2, 3 ]. Consider removing it for consistency.

Apply this diff:

-    expect(arr).toEqual([1, 2, 3 ])
+    expect(arr).toEqual([1, 2, 3])
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc8d7be and d58b43c.

📒 Files selected for processing (2)
  • packages/query-core/src/__tests__/streamedQuery.test.tsx (1 hunks)
  • packages/query-core/src/streamedQuery.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/query-core/src/streamedQuery.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Applied to files:

  • packages/query-core/src/__tests__/streamedQuery.test.tsx

@HuijungYoon
Copy link
Author

  • typo correction
  • fix correct test case

@HuijungYoon HuijungYoon reopened this Dec 15, 2025
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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d58b43c and 7a81504.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • .changeset/fair-peaches-deny.md (1 hunks)
  • packages/query-core/src/__tests__/streamedQuery.test.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-02T17:57:33.184Z
Learnt from: TkDodo
Repo: TanStack/query PR: 9612
File: packages/query-async-storage-persister/src/asyncThrottle.ts:0-0
Timestamp: 2025-09-02T17:57:33.184Z
Learning: When importing from tanstack/query-core in other TanStack Query packages like query-async-storage-persister, a workspace dependency "tanstack/query-core": "workspace:*" needs to be added to the package.json.

Applied to files:

  • .changeset/fair-peaches-deny.md
📚 Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Applied to files:

  • packages/query-core/src/__tests__/streamedQuery.test.tsx
🧬 Code graph analysis (1)
packages/query-core/src/__tests__/streamedQuery.test.tsx (1)
packages/query-core/src/streamedQuery.ts (1)
  • streamedQuery (46-97)
🔇 Additional comments (1)
packages/query-core/src/__tests__/streamedQuery.test.tsx (1)

501-536: LGTM! Test correctly validates the bug fix.

The test properly verifies that the reducer is invoked only once per chunk (not twice as the bug was causing). The test also correctly validates the refetchMode: 'replace' behavior where:

  • The reducer is called for each chunk during both initial fetch and refetch
  • During refetch, cache updates are deferred until the stream completes
  • The observable data correctly reflects the replaced stream [1, 2, 3] after refetch

@HuijungYoon HuijungYoon changed the title fix(query-core): prevent reducer from being called twice in streamedQuery #9787 fix(query-core): prevent reducer from being called twice in streamedQuery Dec 15, 2025
# Conflicts:
#	pnpm-lock.yaml
@nx-cloud
Copy link

nx-cloud bot commented Dec 28, 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 ee74b57

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

☁️ Nx Cloud last updated this comment at 2025-12-28 10:13:40 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 28, 2025

More templates

@tanstack/angular-query-experimental

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

@tanstack/eslint-plugin-query

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

@tanstack/query-async-storage-persister

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

@tanstack/query-broadcast-client-experimental

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

@tanstack/query-core

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

@tanstack/query-devtools

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

@tanstack/query-persist-client-core

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

@tanstack/query-sync-storage-persister

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

@tanstack/react-query

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

@tanstack/react-query-devtools

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

@tanstack/react-query-next-experimental

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

@tanstack/react-query-persist-client

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

@tanstack/solid-query

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

@tanstack/solid-query-devtools

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

@tanstack/solid-query-persist-client

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

@tanstack/svelte-query

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

@tanstack/svelte-query-devtools

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

@tanstack/svelte-query-persist-client

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

@tanstack/vue-query

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

@tanstack/vue-query-devtools

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

commit: ee74b57

@TkDodo
Copy link
Collaborator

TkDodo commented Dec 28, 2025

two existing tests are failing for streamedQuery after your change, please take a look

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.

streamedQuery reducer being called twice

2 participants