apollo-client icon indicating copy to clipboard operation
apollo-client copied to clipboard

Infinite query loop, when multiple queries get called

Open mskorokhodov opened this issue 3 years ago • 3 comments

Hey Everyone,

Got a weird issue, when apollo keeps sending queries without an implicit call, somewhere under the hood.

So here are the details: I have 3 queries to be executed same time in my useEffect which is called one time (i did debug). For some reason, if I'll call only for useUi_User_GetExploreChartDataLazyQuery, it works just fine...

Hooks are generated, you can see the sources of one below.

"@apollo/client": "^3.6.2"
const Explore = () => {
  const activeServiceId = useSelector(
    (state: IRootState) => state.service.data?.activeService?.id
  );

  const [filter, setFilter] = useState<api.QueryDataFilter>({
    observedAt_GTEQ: "LAST_24_HOURS",
    ...(userPreferences.get("exploreFilters") ?? {}),
  });

  const [getExploreChartData] = api.useUi_User_GetExploreChartDataLazyQuery();
  const [getExploreTreeData] = api.useUi_User_GetExploreTreeDataLazyQuery();
  const [getExploreCoverageData] = api.useUi_User_GetExploreCoverageDataLazyQuery();

  useEffect(() => {
    console.count("useEffect, [activeServiceId, filter]");

    if (activeServiceId) {
      const variables = processVariables({
        service_id: activeServiceId,
        filter,
      });

      getExploreChartData({ variables });
      getExploreTreeData({ variables });
      getExploreCoverageData({ variables });
    }
    userPreferences.set("exploreFilters", filter);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeServiceId, filter]);

  return null;
}
export function useUi_User_GetExploreChartDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<Ui_User_GetExploreChartDataQuery, Ui_User_GetExploreChartDataQueryVariables>) {
  const options = {...defaultOptions, ...baseOptions}
  return Apollo.useLazyQuery<Ui_User_GetExploreChartDataQuery, Ui_User_GetExploreChartDataQueryVariables>(Ui_User_GetExploreChartDataDocument, options);
}

mskorokhodov avatar May 13 '22 22:05 mskorokhodov

@mskorokhodov Just in case it helps, can you try updating to the latest beta release with npm i @apollo/client@beta (which will give you version 3.7.0-alpha.4)?

benjamn avatar May 13 '22 22:05 benjamn

@benjamn issue is still there...

mskorokhodov avatar May 13 '22 22:05 mskorokhodov

I'm a similar issue to this as well as of v3.9.4. Here's the pattern as I see it:

  1. ComponentA runs a query on MyField, and includes an ID for caching
  2. ComponentB runs a different query on MyField.
  3. Apollo updates the MyField cache to merge in data from Component B
  4. The cache update changes the value for SyncExternalStore, an internal of the useQuery hook.
  5. ComponentA is re-rendered due to the hook value change
  6. ComponentA re-executes the original query on MyField.

As additional components that use various queries on MyField are added, the number of re-renders of each of them increases.

Removing id (or whatever the cache key field is) from any of the queries circumvents the problem by preventing the result from caching.

So far, the only thing I've found that seems to fix it is to set nextFetchPolicy to cache-only. I'm still curious whether this is expected behavior, or if there are other ways to fix it?

wfischer42 avatar Feb 12 '24 23:02 wfischer42