Skip to content

Unexpected staleTime of 1000ms set on fetchQuery #8986

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

Closed
lucas0530 opened this issue Apr 10, 2025 · 1 comment
Closed

Unexpected staleTime of 1000ms set on fetchQuery #8986

lucas0530 opened this issue Apr 10, 2025 · 1 comment

Comments

@lucas0530
Copy link

Describe the bug

Issue Description

When using react-query's fetchQuery under certain conditions, the staleTime option is unintentionally set to 1000ms internally, even though it was not explicitly specified.

Steps to Reproduce

Execute a fetchQuery on page A with a specific query key without explicitly setting staleTime.

Execute useSuspenseQuery on page B with the same query key, which internally sets staleTime to 1000ms.

Navigate back to page A and execute fetchQuery again with the same query key. It unintentionally reuses the previously set 1000ms staleTime.

Your minimal, reproducible example

https://codesandbox.io/p/devbox/intelligent-carlos-forked-dnf7d7?workspaceId=ws_3jAYUrwzD7RnnukpanRdE9

Steps to reproduce

  1. When the Test button is clicked, the cache is stored without an explicitly set staleTime option.
  2. Upon clicking the Show button, the existing cache is updated with a staleTime of 1000ms (due to the previous internal ensure utility logic).
  3. Clicking the Test button again maintains the cache with the previously set staleTime of 1000ms.
  4. If the Show button is clicked again within 1000ms after step 3, the queryFn does not get triggered.

It appears that because fetchQuery executes with a 1000ms staleTime, useSuspenseQuery considers the given query key fresh and avoids invoking the queryFn.

Expected behavior

Additional Issue Caused

Due to this behavior, if useSuspenseQuery is executed again within 1000ms after step 3 with the same query key, it considers the data as fresh. Therefore, the queryFn for background fetching does not get called at all, leading to potential issues of not retrieving up-to-date data from the server.

Expected Behavior

When not explicitly set, fetchQuery should use the default staleTime of 0ms as documented.

Options from useSuspenseQuery should not unintentionally affect subsequent fetchQuery calls. Each query should handle its options independently.

How often does this bug happen?

None

Screenshots or Videos

No response

Platform

  • MacOS
  • Chrome All Versions

Tanstack Query adapter

None

TanStack Query version

v4, v5

TypeScript version

No response

Additional context

No response

@TkDodo
Copy link
Collaborator

TkDodo commented May 1, 2025

Navigate back to page A and execute fetchQuery again with the same query key. It unintentionally reuses the previously set 1000ms staleTime.

That’s not what’s happening. I’ve modified your example to show more log statements from within the QueryFunctions: https://codesandbox.io/p/sandbox/intelligent-carlos-forked-hrlkk9?file=%2Fsrc%2FApp.tsx%3A37%2C7

You can see that whenever you click TEST, the queryFn is executed. The staleTime is not reused. It can’t be reused because staleTime is an observer-level property that doesn’t exist on a Query - it exists on QueryObserver (and is amended for imperative methods like fetchQuery).

So, you can call fetchQuery whenever you want, it will execute.

if useSuspenseQuery is executed again within 1000ms after step 3 with the same query key, it considers the data as fresh. Therefore, the queryFn for background fetching does not get called at all, leading to potential issues of not retrieving up-to-date data from the server.

Yes, useSuspenseQuery has a “minimal” staleTime of one second. That’s necessary because of how suspense works: it unmounts your component to show the fallback. Then, once data comes in, it will mount your component again. With a staleTime of zero that would trigger another immediate background refetch, which isn’t wanted.

Sorry if this is causing issues for you but I don’t think I’ll be spending time to improve this. The sequence to reproduce is pretty narrow, as you need to have been on the page where useSuspenseQuery is executed, move away from it, trigger a fetch and then within one second move to the page with useSuspenseQuery again. And even then, you’ll get data from roughly 500ms “before”.

If that’s really an issue, you can always run queryClient.fetchQuery() in a useEffect in addition on the page where you call useSuspenseQuery.

@TkDodo TkDodo closed this as not planned Won't fix, can't repro, duplicate, stale May 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants