Refetch Inactive Queries

I have an app which is effectively a calendar.

In a view, you see one person’s events. I get an array of events with queries are like:

  • calendar(‘Bob’, ‘January’)
  • calendar(‘Adam’, ‘January’)
  • calendar(‘Bob’, ‘February’)

When I mutate an event, I do roughly this:

export const useMutateEvent = (variables) => {
  const [mutateEvent] = useMutation(MUTATE_EVENT, {
    refetchQueries: [GET_USER_CALENDAR],
    onQueryUpdated(observableQuery) {
      if (
        observableQuery.queryName === 'calendar' &&
        observableQuery.options?.variables?.user === variables.user
      ) {
        return observableQuery.refetch();
      }

      return false;
    },
  });

  return (event) => {
    return mutateEvent({ variables: { event } });
  };
};

This works great and I can see the updates in the calendar I am in. However, for longer events, when I go to another month I have already viewed, the changes are not reflected.

How should I indicate I need these inactive queries to be refetched as well?

Thanks

For others that may run into this problem, the fix is to evict data from the ROOT_QUERY.

Any of these should work in varying amounts of collateral, depending on how much you want to refetch later.

cache.evict({ fieldName: 'calendar' });
cache.evict({ fieldName: 'calendar', args:{ user:'Bob', month:'January' });

I wanted to evict based on only one argument, so I made a helper function to find all matches with only a partial set of variables.

export const fuzzyEvict = (cache, args) => {
  const rootQueries = cache?.data?.data?.ROOT_QUERY;
  if (!rootQueries) return false;

  let evict;
  for (let k1 in rootQueries) {
    if (k1.indexOf(args.fieldName + '(') === 0) {
      evict = true; //Maybe evict if the args match
      for (let k2 in args.args) {
        //Example of a key value: calendar({"user":"Bob","month":"January"})
        if (
          !k1.match(new RegExp('"' + k2 + '":["|]' + args.args[k2] + '["|,|}]')) 
        ) {
          //Check each key exists, and the value is there
          evict = false;
          break;
        }
      }
      if (evict) {
        cache.evict({ fieldName: k1 });
      }
    }
  }
};

Which allows me to do this:

fuzzyEvict(cache, {
  fieldName: 'calendar',
  args: { user: 'Bob' },
});

So my function is now something like:

export const useMutateEvent = (variables) => {
  const [mutateEvent] = useMutation(MUTATE_EVENT, {
    update(cache) {
      fuzzyEvict(cache, {
        fieldName: 'calendar',
        args: { user: variables.user },
      });
    },
  });

  return (event) => {
    return mutateEvent({ variables: { event } });
  };
};