Search code examples
reactjsreact-query

react-query: how to get the data from useQuery in onSuccess callback?


I am learning react-query and I meet some problems. I want to use the data I get from fetching data by useQuery, but I get data as undefined. Here is my code:

import React from "react";
import { useQuery } from "react-query";
import { fetchData } from "./providesData";
const Home = () => {
  const {data} = useQuery("fetchData", fetchData, {
    onSuccess: () => {
      console.log("Get data!");
      console.log(data); // undefined
    }
  });

  return <div></div>;
};

export default Home;

But I see in react-query devtools that the fetch is succeeded and the data is here. So I think I do not access the data in my onSuccess callback properly. So how can we get access to the data in the callback? I tried:

const query = useQuery("fetchData", fetchData, {
    onSuccess: () => {
      console.log("Get data!");
      console.log(query.data); // undefined
    }
  });

but still no luck.

I read the documentation and found this:

onSuccess: (data: TData) => void

So I tried this in my code:

const {data} = useQuery("fetchData", fetchData, {
    onSuccess: (data: TData) => {
      console.log("Get data!");
      console.log(data); // success
    }
  });

This time it works. But I do not understand why... And the code editor also warned me:

Type annotations can only be used in TypeScript files.ts(8010)

Can anyone show me the right way to do it? Thank you so much!

Here is a demo.


Solution

  • The onSuccess callback function is called only when the data has been retrieved from the query. Carefully notice that this data is not the one that you're de-structuring from the useQuery return object, but the one that has been passed to the callback on successful retrieval of data from your API. Since, it is a callback function, you don't need to check for waiting/loading cases, as it will eventually be called if your request succeeds.

    In your case, the first data variable will return undefined as soon as the Home component mounts, because the useQuery call is an asynchronous call which means that data returned from the useQuery call will need to be resolved from a Promise. Thus, it will not be directly available as soon as the Home component mounts, but only after the query resolved successfully. Also, react-query useQuery hook calls the onSuccess(data) callback with the data received before the actual data object(the one returned by the useQuery hook) is set and returned from the hook.

    Since useQuery is an asynchronous call (internally), it also provides request in-flight flags like isLoading, isFetching, etc. which you can use to null-check for data, errors, or any other purpose suitable.