skip to Main Content

In my application, I use react-query to handle fetching data. I use useQuery to receive data in my components. The code for this is shown below:

   const { isLoading, data} = useQuery('albums', fetchAlbums)

   const fetchAlbums = () => {
      const res = await axios.get('/albums')
      return res.data
   }

   return (
      isLoading ? <Spinner /> :
      <div>
         // When clicking this button, check if there is new data from the api endpoint, and if so, set data variable to the new data
         <button>Refetch data</button>

         // Display the data
         {data}
      </div>
   )

The code above works fine, however when the button displayed is clicked, it should check if there is new data from the endpoint specified in fetchAlbums and if there is new data from the endpoint, update the data variable for albums and display the new data. The issue I have is that I want the old data to still be displayed whilst the refetch occurs (i.e after the button is clicked), and if there is new data, then replace the old data displayed with the new data. How could I potentially accomplish this? Thanks.

3

Answers


  1. I believe that what you would look to do is to call invalidateQueries() to invalidate the query, and then on next render of the component your call to useQuery() should refetch the data from the server instead of getting the data from cache.

    Login or Signup to reply.
  2. By default, useQuery fetches immediately when the component calling it mounts, but not everyone wants this behaviour.

    Method 1: Enabled Boolean

    You’re able to set the default behaviour to NOT fetch data immediately using a key enabled and setting it to false

      const { data } = useQuery("comments", fetchComments, {
        enabled: false
      });
    

    If we want to use a button to trigger this we can maintain a piece of state that holds true or false and then pass the setEnabled method to a button.

    On click, the query will fetch the data.

    const [enabled, setEnabled] = useState(false);
    const { data } = useQuery("comments", fetchComments, {
        enabled: enabled
      });
    <button onClick={() => setEnabled(true)}>Some Button</button>
    

    Method 2: Refetch()

    My preferred method is to use refetch . This is a method that comes with useQuery and is closer to the functionality many of us are looking for in this scenario.

    The data is not fetched automatically. We have turned it off using enabled: false.

    We can then pass the refetch method to our button to grab the data on demand without toggling any state.

    export const useComments = () => {
      const { data, refetch } = useQuery("comments", fetchComments, {
        enabled: false
      });
    <button onClick={() => refetch()}>Some Button</button>
    
    Login or Signup to reply.
  3. I would agree with Greg’s response. There are a few conceptual methods you could use for this. I think this podcast episode of Syntax FM covers this in the vein of cache handling.
    Hope this helps, good luck!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search