DEV Community

Cover image for React-query series Part 4: Interacting with the cache using the useQueryClient hook.
Emmanuel Chinonye Nnajiofor
Emmanuel Chinonye Nnajiofor

Posted on

React-query series Part 4: Interacting with the cache using the useQueryClient hook.

Cover image by Lawrence Eagles in the article: Whatโ€™s new in React Query 3

Hey everyone ๐Ÿ‘‹

It took a little while but I'm back again. I am always grateful for the encouragement. My special appreciation to my new followers:
@maxm , @sgrajan1 , @ossygarcia , @mehzan07 , @hi_im_ml, @fernado27 , @gmazur92 , and many others I cannot all mention for obvious constraints. I use this space to talk about frontend development, react-js especially. I intend to cover topics on strapi-js also.
In Part Three: Data fetching with the useQuery hook, we talked about how to fetch data using the useQuery hook, passing variable(s) to our query function, and lastly, overriding our global default configuration on a single query instance.

Table of contents

Intro

If you have been following this series since Part One: Basic react-query setup, you may have running through your mind these questions; I have learned how to set up this library, fetch data, but how does react-query reduce or eliminate my dependence on global store library like redux? How do I get data from a query instance in the Foo.js component to the Bar.js component without using a global store or by passing props around? What if I'd like to refetch a query initially called somewhere in my app-how do I get this cache to work for me? These are the questions I intend to answer in this part of the series. We are going to see how to interact with the cache from anywhere in our application. Some of the actions we can perform on the cache include but are not limited to prefetching a query, getting the current state of a query(ries), getting query data, setting a new query default, etc.

The useQueryClient hook

The useQueryClient hook (to not be confused with the useQuery hook or QueryClient) is our entry point to interacting with our query cache. The useQueryClient hook returns the instance of the current QueryClient of our application. We import useQueryClient from react-query thus

import { useQueryClient } from 'react-query'

 const queryClient = useQueryClient()
Enter fullscreen mode Exit fullscreen mode

queryClient in the snippet above provides us a couple of methods to interact with the cache. We destructure some of these methods inline thus

import { useQueryClient } from 'react-query'

 const {
    prefetchQuery,
    fetchQuery,
    getQueryData,
    refetchQueries,
    getQueryState,
    setQueryDefaults,
    clear,
  } = useQueryClient();
Enter fullscreen mode Exit fullscreen mode

There exist more methods from this object, but we are only taking this few I feel are most important. Do find time to look at a full list of these methods here.

prefetchQuery

Do you need to fetch data in some part application before the user needs it? then prefetchQuery is what you need.
prefetchQuery is used to prefetch a query before it is needed or rendered by useQuery. By using this asynchronous method, you will spare your users the dreaded loading spinners because the query data already exists, react-query only goes to refresh this data behind the scenes if it is stale as per your QueryClient configurations.

await prefetchQuery(queryKey, queryFn)
Enter fullscreen mode Exit fullscreen mode

prefetchQuery accepts a query key and a query function to prefetch.

await prefetchQuery(queryKey)
Enter fullscreen mode Exit fullscreen mode

You can also pass only a query key if you have a default query function set in your QueryClient configuration.

await prefetchQuery(queryKey, queryFn, {
     staleTime: 10000,
})
Enter fullscreen mode Exit fullscreen mode

prefetchQuery also takes a configurations object as a third parameter. The snippet above will prefetch a query only when the data is older than 10 seconds.

fetchQuery
fetchQuery is somewhat similar to prefetchQuery. It is used for fetching and caching a query. It either returns the data from the query or throws an error. If a query exists in the cache and data is not stale, it returns the data, else it goes on to fetch the query.

fetchQuery accepts a query key and a query function.

try {
   const data = await fetchQuery(queryKey, queryFn)
 } catch (error) {
   console.log(error)
 }
Enter fullscreen mode Exit fullscreen mode

You can also pass a config object as a third parameter.

try {
   const data = await queryClient.fetchQuery(queryKey, queryFn, {
     staleTime: 10000,
   })
 } catch (error) {
   console.log(error)
 }
/*
will fetch a query only when the data is older than 10 seconds.
*/
Enter fullscreen mode Exit fullscreen mode

fetchQuery and prefetchQuery accepts configurations options just like the useQuery hook with exception of the following : enabled, refetchInterval, refetchIntervalInBackground, refetchOnWindowFocus, refetchOnReconnect, notifyOnChangeProps, notifyOnChangePropsExclusions, onSuccess, onError, onSettled, useErrorBoundary, select, suspense, keepPreviousData, placeholderData.

getQueryData

This method is used to get an existing query's data. You can get data from any existing query anywhere in your application.

const data = getQueryData(queryKey)
Enter fullscreen mode Exit fullscreen mode

It returns the data if it exits or undefined if it doesn't.

const data = getQueryData(queryKey)
Enter fullscreen mode Exit fullscreen mode

refetchQueries

refetchQueries is used to refetch queries based on a certain condition. It accepts an optional query key and/or query filter as parameters.
Read more about query filters here

// this will refetch all queries in the app:
 await refetchQueries()

 // this will refetch all stale queries:
 await queryClient.refetchQueries({ stale: true })

 /* this will refetch all active queries partially matching a query key "posts" */:
 await refetchQueries(['posts'], { active: true })

 // refetch all active queries exactly matching a query key:
 await refetchQueries(['posts', 1], { active: true, exact: true })
Enter fullscreen mode Exit fullscreen mode

getQueryState

This function is used to get the state of an existing query. It returns undefined if this query does not exist. You can use this method to show loading, error, or success feedback for any query anywhere in your application.

const state = getQueryState(queryKey)
//checking if this query is currently loading.
 console.log(state.isLoading)
Enter fullscreen mode Exit fullscreen mode

setQueryDefaults

This method is used to set default options for a query. It accepts a query key and an options object.

/*
sets a new 'cacheTime' default option for this query, overriding the global 'cacheTime' default option
*/

setQueryDefaults('posts', { cacheTime: 10000})

 function Component() {
   const { data } = useQuery('posts')
 }
Enter fullscreen mode Exit fullscreen mode

clear

This methods simply clears all cache your application may be connected to.

Conclusion

We have seen that with the useQueryClient hook, we can start interacting with everything in our cache including getting a query's data, fetching a query refetching a query(ries), clearing our cache, etc.
In the next part, we will see how can start making mutating actions to our server i.e. the create/update/delete using the useMutation hook.

Thank you all for your support. If you are beginner and haven't written something, do that today! Please give me a ๐Ÿ’– if this post or part of it has helped you. Comments are welcomed too.
Follow me on twitter @NnajioforEmma10

Table of contents

Discussion (0)