Invalidate cache of Dependent Queries in React Query

One of my favourite library in React ecosystem is React-Query. If you don't know about it already, React-Query helps you to fetch, cache and manage server state in your react application. It is fully customizable and requires zero-configuration out of the box.

useQuery hook

One of the most useful hook that React-Query Provides is useQuery which is used to fetch data from server. It takes key( unique key for the query ), resolver( function that returns a promise ) and config object ( configuration object using which the query can be customized ), and returns an object containing bunch of useful properties like query state, data, error etc.

import { useQuery } from 'react-query';

export default function Post({ id }) {
  const { status, data, error } = useQuery("post", () => axios.get(`/some-post/${id}`), { staleTime: Infinity } );
}

In the above code, we can observe that :

  • 1st argument is "post" which is a unique key for this query
  • 2nd argument is function that returns promise. Here, we're using axios to return promise
  • 3rd argument is config object where we've set the stale time to infinity for our cache

Dependent Queries

As the name suggests, Dependent queries are dependent on some condition and wouldn't run automatically ( like on component mount ) unless the condition is met. To make a query dependent, we just need to pass a boolean flagenable in the config object.

import { useQuery } from 'react-query';

export default function Post({ id }) {
  const { status, data, error } = 
        useQuery("post", 
                        () => axios.get(`/some-post/${id}`), 
                        {
                           enable: false, 
                           staleTime: Infinity 
                        } 
        );
}

There are many scenarios where we would need a query like this. For example, suppose we want to fetch and show specific post in the modal only when user clicks on that particular post from array of posts. So in this case, our query is dependent on post id and hence, we can pass enable: !!id in config object to make it dependent query.

import { useQuery } from 'react-query';

export default function Post({ id }) {
  const { status, data, error } = 
        useQuery("post", 
                        () => axios.get(`/some-post/${id}`), 
                        {
                           enable: !!id, 
                           staleTime: Infinity 
                        } 
        );
}

Invalidate Cache of Dependent Queries

But the things get tricky when you try to invalidate the cache of dependent queries because these queries will ignore query client invalidateQueries and refetchQueries calls that would normally result in the query refetching.

So to invalidate the cache, you need to manually refetch the query using refetch method that useQuery hook returns.

  // inside the component
  const { refetch } = 
        useQuery("post", 
                        () => axios.get(`/some-post/${id}`), 
                        {
                           enable: !!id, 
                           staleTime: Infinity 
                        } 
        );

  // calling refetch whenever user clicks on button to refetch the post
  const handleFetchPostOnClick = () => refetch()
}

And that's how you can invalidate the cache of dependent queries.

Bonus tip : You can also provide complex key like ["post", id] which will fetch the query everytime id changes

import { useQuery } from 'react-query';

export default function Post({ id }) {
  const { status, data, error, refetch } = 
        useQuery(["post", id], 
                        () => axios.get(`/some-post/${id}`), 
                        {
                           enable: !!id, 
                           staleTime: Infinity 
                        } 
        );

}

Thanks for reading.