streamedQuery reducer being called twice
Describe the bug
It seems the streamedQuery's reducer is being called twice, resulting in duplicated values. Please see the relevant code:
https://github.com/TanStack/query/blob/ecdf96296b1dfcee617a5a5b9afdf2a42ad436ba/packages/query-core/src/streamedQuery.ts#L83C1-L89C38
// don't append to the cache directly when replace-refetching
if (!isRefetch || refetchMode !== 'replace') {
context.client.setQueryData<TData>(context.queryKey, (prev) =>
reducer(prev === undefined ? initialValue : prev, chunk),
)
}
result = reducer(result, chunk)
As you can see, reducer gets called once in the setQueryData under special conditions, and then again at the end of the loop. This can mess up a stateful object in a custom reducer.
Your minimal, reproducible example
It's very simple
Steps to reproduce
const arr = [];
queryOptions({
queryKey: ["somekey"],
queryFn: streamedQuery({
streamFn: async function* (ctx) {
const v = [1, 2, 3];
yield* v;
},
reducer: (oldStream, newChunk) => {
arr.push(newChunk);
return [...oldStream, newChunk];
},
initialValue: [],
refetchMode: "replace",
}),
arr.length == 6
Expected behavior
Reducer gets called once per chunk.
How often does this bug happen?
None
Screenshots or Videos
No response
Platform
Windows
Tanstack Query adapter
None
TanStack Query version
v5.90.5
TypeScript version
No response
Additional context
No response
reducer is supposed to be a pure function, not something that writes to a global value. In that sense, I don’t think it matters much, but we can also capture the result of the reducer in the if statement and re-use for the result assignment.
If you want to improve this, please add a failing test-case & a fix and open a PR 🙏
Hi @TkDodo, I've updated this and pushed the changes. Could you take a look at the PR when you get a chance?