1

This is the custom hook

export const useFilteredProfiles = (filters) => {
    const { type, state, occupancy, propertyValue, loanToValue } = filters
    return useQuery({
        queryKey: ['profiles', type, state, occupancy, propertyValue, loanToValue]
        , queryFn: ({ queryKey }) => fetchData(queryKey),
        refetchOnWindowFocus: false,
        retry: false,
        staleTime: Infinity,
        enabled: !!type
    });
}

which I used in two components on separate pages

There are filters on first page using these filter state I use above hook to fetch and show count of profiles present.

There is button in first page onClick I pass these filter states in router query (as show in below code)

To use filter state in another page to get cached profiles data, but it makes api request there instead of getting it from cache.

 const handleClick = () => {
        router.push({ pathname: `${router.pathname}/profiles`, query: { type, state, occupancy, propertyValue, loanToValue } });
    }

Am I doing something wrong?

4
  • check if it might be this: tkdodo.eu/blog/… Commented Nov 26, 2022 at 7:58
  • No this is not issue with my code. I have created queryClient outside App component Commented Nov 27, 2022 at 7:36
  • @TkDodo I think the issue is with next/router return empty query object initially. I tried to handle this with enabled attribute in above code. Commented Nov 27, 2022 at 7:37
  • you'd need to show a codesandbox reproduction then please Commented Nov 27, 2022 at 15:12

3 Answers 3

1

React Query will cache the data of the query by default, but that does not affect whether or not it thinks that data is stale. If it thinks data is stale, it will call the query function (hit the API) every time useQuery() is called. This means it will read the data from the cache if it has it, but since it thinks that data is stale, will still hit the API in the background to fetch any updated data.

Fortunately, you have complete control over whether or not React Query considers data to be stale. You can set a staleTime config option to control how long specific data should be considered fresh. You can even set it to Infinity to say that as long as your app is open, it should only ever call the query function (hit the API) one time. By default this value is 0, which is why you are seeing the behavior you are - React Query will refetch the data in the background every time useQuery is called because it immediately thinks that data is stale (even though it's still cached).

In your example, if you truly ever only wanted an API to be called one time, you could simply set the staleTime option to Infinity.

useQuery("myStuff", getMyStuffQuery().queryFn, { staleTime: Infinity });

This option, along with all others, can be read about in the docs here https://react-query.tanstack.com/reference/useQuery

Sign up to request clarification or add additional context in comments.

1 Comment

I have already used staleTime check my code above
0

You can initialize queryClient first and check if data with that key is exists or not on react-query cache storage

import { useQuery, useQueryClient } from 'react-query';
const queryClient = useQueryClient();

export const useFilteredProfiles = (filters) => {
const { type, state, occupancy, propertyValue, loanToValue } = filters
    return useQuery({
        queryKey: ['profiles', type, state, occupancy, propertyValue, loanToValue]
        queryFn: ({ queryKey }) => fetchData(queryKey),
        refetchOnWindowFocus: false,
        retry: false,
        enabled: !queryClient.getQueryData(['profiles', type, state, occupancy, propertyValue, loanToValue])
    });
}

Comments

0

Problem: Other component is also fetching data, while it's already present in cache.

Reason: The QueryClient holds the QueryCache, so if you create a new client, you also get a new cache, which will be empty. If you move the client creation into the App component, and your component re-renders for some other reason (e.g. a route change), your cache will be thrown away.

Image: See this Image for better understanding

Solution: Move Your QueryClient Object outside of the component defination or put it inside useState so that object won't change on re-render.

Reference: the-queryclient-is-not-stable

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.