-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
React Query - Missing fetchStatus changes for disabled queries with dynamic keys #8741
Comments
This is quite interesting. The problem is that your first observer is permanently disabled, because it’s called with Each observer tries to determine what the next state of the query will be, synchronously, to avoid having to wait for the fetch to actually happen. so query/packages/query-core/src/queryObserver.ts Lines 469 to 474 in 5d69ad7
Now when the first observer re-renders, it will see that it’s disabled and for all it knows, there won’t be a fetch coming, so it says I don’t think there’s a good way to fix this, as this observer doesn’t have more info when rendering. There’s also no additional render happening when the fetch is actually triggered because we have already computed that state optimistically. That exception is here: query/packages/react-query/src/useBaseQuery.ts Lines 116 to 120 in 2bf7ec6
now MAYBE we could remove that not sure if this helps with your actual issue @istrel, but re-writing the sandbox to only disable the query when there is no id makes everything work, too: https://stackblitz.com/edit/tanstack-query-nmvt14tm?file=src%2Findex.tsx&preset=node that’s the usual approach to go about this, but I guess there is a reason why this one observer is permanently disabled? |
The reason why the observer is permanently disabled is that it's used in other place for showing the spinner. We have code similar to this: const id = useAtomValue(idAtom);
const commonQuery = useCommonQuery({ id, enabled: false })
const queryForTab1 = useTab1Query({ id, enabled: false })
const queryForTab2 = useTab2Query({ id, enabled: false });
const isAnythingLoading = [
commonQuery,
queryForTab1,
queryForTab2,
].some(q => q.isFetching);
return <RouterLayoutComponent>
{loading ? <Spinner /> : null}
<Outlet />
</RouterLayoutComponent> If we enable query it would trigger the request for the other tab even if it's not shown. This is not what we want because the HTTP request made is pretty big. I know that we have |
Interesting indeed, thanks for reporting this!
I think this sounds very reasonable! I can see why |
we have an optimized `shouldNotifyListeners` logic internally in the QueryObserver that will make sure we only notify listeners that are interested in a change because they are using a specific key (tracked query properties) the optimization to force a skip of the notification when updating options because the optimistic result should already contain all the necessary output falls apart in the situation described in the test and in the linked issue #8741. while the issue itself is a niche edge-case, the fix is to actually remove a bunch of code, so I'm all for it
Describe the bug
If you use
useQuery
withenabled: false
and dynamic keys you can miss re-renders because of missingfetchStatus
updates.I.e. in this example (also posted on codesandbox) provided re-render will be triggered only when fetching the data is complete.
Your minimal, reproducible example
https://codesandbox.io/p/devbox/solitary-rgb-7szrj2
Steps to reproduce
Run the example (it's the copy of codesandbox) and press the button "Set ID and trigger user load":
Expected behavior
Expected behavior:
User fetching status is fetching
until the user info is updatedActual behavior:
User fetching status is idle
How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
Tanstack Query adapter
None
TanStack Query version
5.66.11
TypeScript version
5.7.3
Additional context
Here are some of the factors which matter for bug reproducibility:
queryKey
instead of dynamic makes the bug disappear<div>User fetching status is {searchQuery.fetchStatus}</div>
to a separate component may make the bug disappear)useIsFetching
) the bug is not reproducedThe text was updated successfully, but these errors were encountered: