Home > Mobile >  Rejected query in inner component
Rejected query in inner component

Time:09-03

TL;DR: Why can't I use "key_one" in both cases?

When a request fails, it causes weird behavior in the following situation: Parent component and child component use the same query key.

Is there something I've missed? If I use different keys "key_one" and "key_two", my app fails gracefully. If I use the same key, my app falls into a loop. In the working example I've used 'key_one' and 'key_two'. This is not optimal, as in normal circumstances I want them to be the same for caching reasons.

Intended result: enter image description here

Working code:

async function doFetch() {
  throw new Error("Network response was not ok");
}

function MyInnerComp() {
  const { isError, error } = useQuery("key_one", doFetch);

  return (
    <div style={{ border: "1px solid", padding: "10px" }}>
      <h2>Hello from inner component!</h2>
      {isError && <div>Error! {error.message}</div>}
    </div>
  );
}

function Comp() {
  const { isLoading, isError, error } = useQuery("key_two", doFetch);

  if (isLoading) return <div>loading</div>;

  return (
    <div style={{ border: "1px solid", padding: "10px" }}>
      <h2>Parent component.</h2>
      {isError && <div>Error! {error.message}</div>}
      <hr />
      <div>lorem ipsums</div>
      <MyInnerComp />
    </div>
  );
}

Codesandbox: https://codesandbox.io/s/dry-waterfall-21q741?file=/src/index.js

CodePudding user response:

  1. At the very start Comp render and no data has been fetched => useQuery start fetch and isLoading is updated to true
  2. isLoading = true => Comp then render <div>loading</div>
  3. Data is fetched => isLoading = false
  4. isLoading = false => Comp render <div>...<MyInnerComp /></div>
  5. MyInnerComp render => useQuery of MyInnerComp trigger a refetch (as it was rendered after the query was done) => update isLoading to true
  6. => Comp render again due to isLoading (of the same key) being updated => it render loading and MyInnerComp is unmounted
  7. ... infinite loop that trigger query again and again (MyInnerComp will be mounted again like a fresh new component which retrigger useQuery)

In case you use different key, when MyInnerComp render, it does not update isLoading of key_one which does not trigger the loop

If I'm not wrong a solution might be to use isFetched:

function Comp() {
  const { isLoading, isFetched } = useQuery("key_one", doFetch);

  if (isLoading && !isFetched) return <div>loading</div>;

  return (
    <div style={{ border: "1px solid", padding: "10px" }}>
      <h2>Parent component.</h2>
      {isError && <div>Error! {error.message}</div>}
      <hr />
      <div>lorem ipsums</div>
      <MyInnerComp />
    </div>
  );
}

CodePudding user response:

Instead of doing another query you could try to pass it as props / use it directly. Use the error and isLoading directly in the other component

  • Related