18

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.

Shiqi
  • 837
  • 1
  • 10
  • 18
  • 1
    regarding your error: `:TData` is Typescript syntax. Leave it out if you are using JavaScript – TkDodo Jun 28 '21 at 06:34
  • @TkDodo Yeah, I am only using JavaScript. But weirdly it works. – Shiqi Jun 28 '21 at 10:32
  • if you are fetching data with a post request, it probably means you want to use `useMutation` instead of `useQuery`. `useMutation` will have the data as a parameter of the config callback `onSuccess`, while `useQuery` has data only if you are making a get request. – Fed Jul 30 '21 at 11:05

2 Answers2

18

I just did this:

useQuery("fetchData", fetchData, {
    onSuccess: (data) => {
      console.log("Get data!");
      console.log(data);
    }
  });
Stephan Du Toit
  • 789
  • 1
  • 7
  • 19
16

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.

Sowmen Rahman
  • 344
  • 2
  • 5
  • 4
    Thanks for your reply. I thought `onSuccess` would be called after the `Promise` was resolved. So if I want to do something after the `Promise` is resolved, I should do `if(isSuccess) console.log(data)`. – Shiqi Jun 28 '21 at 10:30
  • Hi, can i return jsx element onSuccess ? – Gurupal singh Dec 06 '21 at 16:22