TanStack / query

🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.
https://tanstack.com/query
MIT License
42.76k stars 2.92k forks source link

`queryFn` not called when using `initialData`, `initialDataUpdatedAt` (with old date) and `refetchOnMount` disabled #8133

Closed anddoutoi closed 1 month ago

anddoutoi commented 1 month ago

Describe the bug

version: 5.59.0

See https://codesandbox.io/p/sandbox/react-query-initialdataupdatedat-refetchonmount-issue-m5yxps for minimal reproduction.

queryFn is not called if refetchOnMount is false even if initialDataUpdatedAt is old.

This works as expected:

function ComponentWithRefetchOnMount() {
  const queryResult = useQuery({
    queryFn: () => {
      console.log("Calling queryFn");

      return new Promise((resolve) => {
        setTimeout(() => resolve("Query Fn Data"), 2000);
      });
    },
    queryKey: ["refetchOnMount", true],
    staleTime: 1000,
    refetchOnMount: true,
    initialData: "Initial Data",
    initialDataUpdatedAt: 1608412420052, // Sat Dec 19 2020 22:13:40 GMT+0100 (Central European Standard Time)
  });

  return (
    <>
      <strong>{JSON.stringify(queryResult.data, null, 2)}</strong>
      <pre>{JSON.stringify(queryResult, null, 2)}</pre>
    </>
  );
}

while this does not:

function ComponentWithNoRefetchOnMount() {
  const queryResult = useQuery({
    queryFn: () => {
      console.log("Calling queryFn"); // <-- WILL NOT BE CALLED

      return new Promise((resolve) => {
        setTimeout(() => resolve("Query Fn Data"), 2000);
      });
    },
    queryKey: ["refetchOnMount", false],
    staleTime: 1000,
    refetchOnMount: false,
    initialData: "Initial Data",
    initialDataUpdatedAt: 1608412420052, // Sat Dec 19 2020 22:13:40 GMT+0100 (Central European Standard Time)
  });

  return (
    <>
      <strong>{JSON.stringify(queryResult.data, null, 2)}</strong>
      <pre>{JSON.stringify(queryResult, null, 2)}</pre>
    </>
  );
}

Your minimal, reproducible example

https://codesandbox.io/p/sandbox/react-query-initialdataupdatedat-refetchonmount-issue-m5yxps

Steps to reproduce

  1. Use the following code:

    function ComponentWithRefetchOnMount() {
    const queryResult = useQuery({
    queryFn: () => {
      console.log("Calling queryFn");
    
      return new Promise((resolve) => {
        setTimeout(() => resolve("Query Fn Data"), 2000);
      });
    },
    queryKey: ["refetchOnMount", true],
    staleTime: 1000,
    refetchOnMount: true,
    initialData: "Initial Data",
    initialDataUpdatedAt: 1608412420052, // Sat Dec 19 2020 22:13:40 GMT+0100 (Central European Standard Time)
    });
    
    return (
    <>
      <strong>{JSON.stringify(queryResult.data, null, 2)}</strong>
      <pre>{JSON.stringify(queryResult, null, 2)}</pre>
    </>
    );
    }
  2. Change refetchOnMount to false.

Expected behavior

Expect it to work the same way when refetchOnMount is true.

How often does this bug happen?

Every time

Screenshots or Videos

Image

Platform

version: 5.59.0, all platforms

Tanstack Query adapter

None

TanStack Query version

5.59.0

TypeScript version

5.6

Additional context

No response

DogPawHat commented 1 month ago

My reading of https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults is that this is expected behavior. The query is mounted with initialData that is stale, stale data is refetched under mount usually, but refetchOnMount is disabled, so the queryFn never runs.

Is there a use case you have were this behavior is being problematic? Curious why you would combine initialData and setting refetchOnMount to false - if it's for stopping the initial fetch you'd set initialDataFetchedAt to Date.now() and provide a staleTime of like 30 seconds or so.

anddoutoi commented 1 month ago

@DogPawHat this is a bit embarrassing but I think I was a bit tired when I stumbled upon this and judged it as an issue at first. I got it mixed up with refetchOnWindowFocus.

You’re right about the defaults.

Closing this and thanking for the rubber duck debugging.