Search code examples
reactjsreact-query

Is it possible to setQueryData using inclusive query key?


I am unable to set query data using inclusive query keys using react query v4.

Example below which I want it to work, but won't

  const { data, isFetched, fetchNextPage, hasNextPage } = useInfiniteQuery({
    retry: 4,
    retryDelay: 544,
    keepPreviousData: true,
    refetchOnMount: true,
    queryKey: ['key1', 'key2', 'key3'],
    .....
  });

  /// WORKS
  queryClient.setQueriesData<InfiniteData<Data>>(
    ['key1'],
    (prev) => {
      if (!prev) return undefined;
      return {
        ...prev,
        pages: prev?.pages?.map((page) => updater(page)),
      };
    },
  );

  /// WORKS
  queryClient.setQueriesData<InfiniteData<Data>>(
    ['key1','key2'],
    (prev) => {
      if (!prev) return undefined;
      return {
        ...prev,
        pages: prev?.pages?.map((page) => updater(page)),
      };
    },
  );

  /// DOES NOT WORK!
  queryClient.setQueriesData<InfiniteData<Data>>(
    ['key2'],
    (prev) => {
      if (!prev) return undefined;
      return {
        ...prev,
        pages: prev?.pages?.map((page) => updater(page)),
      };
    },
  );

I want to have any keys in that exists within queryKey to work just like how invalidateQuery seems to function. Is this possible?

The docs states

"To update multiple queries at once and match query keys partially, you need to use queryClient.setQueriesData instead."

It seems it wants to match queries partially as in order matters...


Solution

  • Understanding setQueryData's functionality

    setQueryData is used to directly set or update the data for a specific query based on the query key you give it. The query key provided in setQueryData needs to match the query key you used when making the query with useQuery or useInfiniteQuery hook exactly for it to update the cache correctly. This means if your query key in useInfiniteQuery is ['key1', 'key2', 'key3'], you need to use the same array as the query key in setQueryData to update the data of the query.

    Partial Matching: setQueryData can indeed match query keys partially. However, this doesn't mean it disregards the order or the exact structure of the query keys. Partial matching usually refers to a scenario where you have multiple queries with keys like ['key1', 'key2'], ['key1', 'key3'], etc. In those cases, using ['key1'] with setQueryData can potentially update all queries that start with ['key1'].

    Order Matters: If the order in your setQueryData does not match the order in your useInfiniteQuery, it will not recognize it as the same query.

    Solution

    You can check if this solution from TkDodo works for your case or even a better one.


    TLDR;: In summary, for setQueryData to work as you intend, the query key used in setQueryData must match the structure and order of the key used in your query hook. Currently, React Query does not support partial matching without an exact key.