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 } });
};
};