11

Using react-query in new project and having small issue. Requirement is to show loading spinner on empty page before data is loaded and than after user fetches new results with different query to show spinner above previous results.

First case is pretty easy and well documented:

  const { isLoading, error, data } = useQuery(["list", query], () =>
    fetch(`https://api/list/${query}`)
  );

  if (isLoading) return <p>Loading...</p>;

  return <div>{data.map((item) => <ListItem key={item.id} item={item}/></div>

But, cant figure out second case - because, after query changes react-query doing fetch of new results and data from useQuery is empty as result I get default empty array and in that case falls to that condition - if (isLoading && !data.length )

  const { isLoading, error, data=[] } = useQuery(["list", query], () =>
    fetch(`https://api/list/${query}`)
  );

  if (isLoading && !data.length ) return <p>Loading...</p>;

  return <div>
    {data.map((item) => <ListItem key={item.id} item={item}/>
    {isLoading && <Spinner/>}
  </div>

4
  • Why do you need the !data.length condition? Commented Jun 25, 2020 at 18:54
  • To show return <p>Loading...</p> only when I dont have data yet, after I have previous data I want to show that data with Spinner as indication that new data is coming. Commented Jun 25, 2020 at 19:01
  • make a console for data and check whether it's returning any object initially data returning will be undefined Commented Jun 25, 2020 at 19:17
  • Yes, seeing that data is undefined and loading is true Commented Jun 26, 2020 at 7:42

3 Answers 3

25

When you have no cache (first query fetch or after 5 min garbage collector), isLoading switch from true to false (and status === "loading").

But when you already have data in cache and re-fetch (or use query in an other component), useQuery should return previous cached data and re-fetch in background. In that case, isLoading is always false but you have the props "isFetching" that switch from true to false.

In your example, if the variable "query" passed on the array is different between calls, it's normal to have no result. The cache key is build with all variables on the array.

const query = "something"
const { isLoading, error, data } = useQuery(["list",query], () =>
    fetch(`https://api/list/${query}`)
  );

const query = "somethingElse"
const { isLoading, error, data } = useQuery(["list",query], () =>
    fetch(`https://api/list/${query}`)
  );

In that case, cache is not shared because "query" is different on every useQuery

Sign up to request clarification or add additional context in comments.

Comments

3

You can use is isFetching for every time new data is fetched

const { isFetching, isError, isSuccess, data } = useQuery('key', fnc())
if (isFetching) {
    return <LoaderSpinner />
}
else if (isError) {
    return "error encountered"
}
return (
    { isSuccess && data?.map((item) => <li>{item?.name}</li>)}
)

1 Comment

But then cached data doesn't make sense anymore since isFetching is also true when fetching data with existing cached data. I think that isLoading is the better option here.
0

The problem with this code is that it is not checking if the data array is empty before attempting to map over it. If the data array is empty, this code will throw an error. To fix this, the code should check if the data array is empty before attempting to map over it.

const { isFetching, isError, isSuccess, data } = useQuery('key', fnc());
if (isFetching) {
    return <LoaderSpinner />
} else if (isError) {
    return "error encountered"
} else if (isSuccess && data?.length) {
    return data?.map((item) => <li>{item?.name}</li>)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.