gqty-dev/gqty

`useQuery` refetches whenever there's a state change in the same component.

Closed this issue · 2 comments

I already discussed this on discord with @vicary. I just prepared some minimal reproductions to easily check the issue.

Summary

Whenever there's a useState or any state changing variable within the same component where useQuery is. If you check the network requests tab, and change the state (for instance, incrementing a counter), you'll see multiple requests are made on it.

function App() {
  const [count, setCount] = useState(0);

  const authors = useQuery()?.authors;

  return (
    <>
      <h1>Look at Networks Tab</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
      </div>
    <>);
}

Reproductions:

  1. CodeSandbox - Uses AniList API
  2. Blankeos/grats-gqty - A React & GQTY + Grats & Hono.

Workaround

The current workaround for this is to always make a separate component for the useQuery, and also make a separate component for useState where state changes happen.

Also, instead of passing the authors directly, I have to put it in an intermediary variable. I initially thought I had to useMemo the intermediary variable, but no need.

Here's an example of the workaround: CodeSandbox

vicary commented

In short, the refetch behaviour is expected.

In Discord, we've discussed the usage of useEffect, reducing unnecessary renders.

GQty has a few things to consider when you are ready to optimize refetches.

  1. Whether refetchOnRender is enabled in useQuery, and
  2. The cachePolicy option in useQuery, and
  3. The maxAge and staleWhileRevalidate option of the cache in your generated client.

You may want to start with increasing the maxAge option, it would reduce the fetches. If you are used to other GraphQL clients, put Infinity there and it will never refetch automatically.

Thanks for the details @vicary ! Very helpful to know.