#Automatic Query Invalidation
1 messages · Page 1 of 1 (latest)
What you return in the mutationFn should be available... I think that's what Dominik said in a semi-recent response. I'd have to go dig for it
useMutation({
mutationFn: (userId) => api.call(userId),
meta: {
invalidates: [['users'], userId],
},
})
I mean, how can I pass the userId from mutationFn to meta object?
So you're using mutate(userId)? I think if you return userId from your mutationFn, say you do...
mutationFn: async (userId) => {
const result = await api.call(userId)
return {
...result,
userId
}
}
Then you'd have what you need?
Sorry, I don't get it. If I return the object in side mutationFn, then how can I access it in meta option?
You have both mutation and meta available. You might also consider doing a hook for each user, so having something like useUser(userId) and meta will have it
You also have access to variables in the global cache callbacks, which is the input to mutate
That's the piece I was trying to get to, thanks
Yeah I know about variables in the global cache callbacks, but how can I access the variables in the global cache callbacks in a useMutation? I mean, I want to pass the queryKey to the global success callback, and it will be invalidated here
As I mentioned above, in some cases, I need to access the payload from mutation func. Passing payload into the hook is not my case
It sounds like you want a combination of meta and variables within your invalidations. Not sure you can confidently do that across an entire application which is why you might want a hook per user mutation
Yes, that's what I mean
I've come to learn trying to use less hooks is the wrong approach. Moving it to a per user sounds better
onError of the global cache callbacks has this signature:
onError?: (error: unknown, variables: unknown, context: unknown, mutation: Mutation) => Promise<unknown>
so it gets variables, and with mutation.meta, you get meta. You can invalidate depending on those
Btw, may I ask a question about your blog post? Can I make await queryKey optional? For example, invalidates no need to await, and awaits needs to be awaited. Sorry, if my question is silly 😅
useMutation({
mutationFn: updateLabel,
meta: {
invalidates: ['all'],
awaits: ['labels'],
},
})
sure? this is just an example implementation that I've found useful. But it's all custom
I mean, how can I implement it?
Hi, sorry if I bother you. I just want to ask if this is the correct way to optional invalidate queryKeys?
declare module "@tanstack/react-query" {
interface Register {
mutationMeta: {
invalidates?: Array<QueryKey> | QueryKey;
awaits?: Array<QueryKey> | QueryKey;
};
}
}
const isArrayOfQueryKeys = (
invalidates: QueryKey | QueryKey[],
): invalidates is QueryKey[] =>
invalidates.every((keys) => Array.isArray(keys));
const queryClient = new QueryClient({
mutationCache: new MutationCache({
onSuccess: async (_data, _variables, _context, mutation) => {
if (mutation.meta?.invalidates) {
const invalidateKeys = isArrayOfQueryKeys(mutation.meta.invalidates)
? mutation.meta.invalidates
: [mutation.meta.invalidates];
queryClient.invalidateQueries({
predicate: (query) =>
invalidateKeys.some((queryKey) =>
matchQuery({ queryKey }, query),
) ?? false,
});
}
if (mutation.meta?.awaits) {
const awaitKeys = isArrayOfQueryKeys(mutation.meta.awaits)
? mutation.meta.awaits
: [mutation.meta.awaits];
await queryClient.invalidateQueries({
predicate: (query) =>
awaitKeys.some((queryKey) => matchQuery({ queryKey }, query)) ??
false,
});
}
},
}),
})
I don't think this works because you're making a new QueryClient, not using the stable one in your app
No, it's a stable queryClient
Stable doesn’t mean it’s the same one that has all your cached data. You’re instantiating a new one here and only using it locally