johann1301s
johann1301s

Reputation: 544

Can I use react-query to set cache and stale time based on response from query?

Can I use react-query to set cache and stale time based on response from query?

Please see the following code.

import {useQuery} from 'react-query' // v3.39.3

const {data} = useQuery('my-query', () => api.getSomething(), {
  cacheTime: data.cacheTime,
  staleTime: data.staleTime // <-- I dont think this will work though...
})

Is this possible?

Upvotes: 3

Views: 1020

Answers (3)

piotr
piotr

Reputation: 1

Late to the party, but have you tried something like this?

import { useQuery, useQueryClient } from '@tanstack/react-query';

async function getPlaceholderData() {
  await new Promise((r) => void setTimeout(r, Math.random() * 5_000 + 1));

  return {
    staleTime: Date.now() + Math.random() * 60_000 + 1,
    // ...
  };
}

function usePlaceholderData() {
  const queryClient = useQueryClient();
  const queryKey = ['PLACEHOLDER_DATA'];

  return useQuery({
    queryKey,
    queryFn: async () => {
      const data = await getPlaceholderData();
      queryClient.setQueryDefaults(queryKey, { staleTime:data.staleTime });

      return data;
    },
  });
}

queryClient.setQueryDefaults will override options you passed to useQuery/useSuspenseQuery. Since it set default options for given query key, you may need to unset them while invalidating the query.

Tanstack Query docs

Upvotes: 0

Violet Rosenzweig
Violet Rosenzweig

Reputation: 665

This is possible:

useQuery({
  queryKey: ['my-query'],
  queryFn: () => api.doSomething();
  staleTime: ({ state: { data } }) => data?.staleTime ?? 0
});

From my testing, the function runs whenever the query changes (state, etc) and so this staleTime function will run before the query runs the first time. Therefore, the data may be undefined, and a default should be returned. 0 means the query will not keep the initialData (if set) for any time, and will immediately run.

Additionally, cacheTime is now gcTime to more accurately reflect the purpose of the parameter. I wouldn't expect wanting to change this based on a query, as it relates to garbage collection when queries are unused (meaning how long should the data stay in memory when no component is mounted with useQuery called using this query). It seems the devs agree, as the field can only be a number or infinity, not a callback like staleTime.


Reference: Tanstack Query - useQuery docs

Upvotes: 1

Issam Mbarki
Issam Mbarki

Reputation: 17

Yes, you can do it, by using an instance from useQueryClient() with the setQueryData function inside the onSuccess call back function to update cash and stale time, like this:

import {useQuery} from 'react-query' // v3.39.3
const queryClient = useQueryClient();
const {data} = useQuery('my-query', () => api.getSomething(), {
  onSuccess: (res) => {
      //access to the new cash and stale time from the server response
      const {newCashTime,newStaleTime}=res.data
      queryClient.setQueryData("my-query", (prevRes) => {
        return {
          ...prevRes,
          cacheTime: newCacheTime,
          staleTime: newStaleTime,
        };
      });
    },
})

Upvotes: -1

Related Questions