Skip to content

useQuery().promise is not restored when staleTime is set #8120

@ali-idrizi

Description

@ali-idrizi

Describe the bug

I was trying out the new useQuery().promise implementation with the React.use() hook, and noticed two issues with it.

For the reproduction I have a very simple setup similar to the docs. There is an input that updates the q state onChange, and the following query:

useQuery({
  queryKey: [q],
  queryFn: () => getData(q),
  staleTime: 60000,
});

There's also a Data component wrapped in a Suspense, which take the promise of the query above as a prop and calls use on it. The query function takes the q, delays 1s and returns the same:

const getData = async (q) => {
  await new Promise((resolve) => setTimeout(resolve, 1000));
  return { q };
};

The first issue occurs when staleTime is set, and it still has fresh data. In this case it seems that the promise in not being restored, and incorrect data is shown. Here's a screen recording:

2024-10-02.15-23-47.mp4

When typing extra characters, it correctly updated the data. However, when I remove characters (in which case it already had fresh data cached) it doesn't seem to restore the correct promise.

The devtools is showing the correct query as active, and the Data component is re-rendering. but from the console logs it seems to be receiving an incorrect promise.

<Search> requested query: "1234".  received promise results:  {q: '12345'}
<Search> requested query: "123".  received promise results:  {q: '12345'}
<Search> requested query: "12".  received promise results:  {q: '12345'}
<Search> requested query: "1".  received promise results:  {q: '12345'}

This issue does not occur when the queryFn is ran, e.g. when providing a query that is not cached or when staleTime: 0.


And the second one, the suspense is only triggering once, and not when the query changes. In the screen recording you can notice as I type "12345", it no longer triggers the suspense (which has "suspending..." as fallback), but it provides a stale promise, until it's done fetching the data for the new query.

I was expecting the suspense to trigger when the query key changes and it's about to fetch data. I thought the current behavior (i.e. show stale data until the new render is done) would have to be achieved through useDeferredValue instead.

I am not sure if this is the intended behavior, so I am did not create a new issue for it, but please let me know if I should do that.

Your minimal, reproducible example

https://codesandbox.io/p/sandbox/awesome-williamson-k2269m

Steps to reproduce

On the first issue, simply type anything in the input and notice the data under it updating. Now remove characters and notice that incorrect data is shown.

On the second issue, notice the suspense triggering when reloading the page, but not when changing the query (in which case query.isFetching is indeed true).

Expected behavior

Already explained above.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • OS: Windows 11
  • Browser: Chrome
  • Version: 129.0

Tanstack Query adapter

react-query

TanStack Query version

5.59.0

TypeScript version

N/A

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions