T
TanStack9mo ago
aware-green

reference variables in useMutation Key

This question is specific to this blog post: https://tkdodo.eu/blog/automatic-query-invalidation-after-mutations Here is my code:
import { useMutation } from "@tanstack/react-query";

type InstitutionGroup = {
id: string;
phone_numbers: Record<string, string>;
};

export function useInstitutionGroup(id: string) {
return useQuery<InstitutionGroup, Error>({
queryKey: ["institutionGroup", id],
queryFn: (): Promise<InstitutionGroup> => api.get<InstitutionGroup>(`/api/institution-groups/${id}/`)
});
}

export function useInstitutionGroupMutation() {
const queryClient = useQueryClient();
return useMutation({
mutationKey: ["institutionGroup", <{id}>],
mutationFn: ({ id, phoneNumbers }) =>
api.patch<InstitutionGroup>(`/api/institution-groups/${id}/`, { phoneNumbers }),
});
}
import { useMutation } from "@tanstack/react-query";

type InstitutionGroup = {
id: string;
phone_numbers: Record<string, string>;
};

export function useInstitutionGroup(id: string) {
return useQuery<InstitutionGroup, Error>({
queryKey: ["institutionGroup", id],
queryFn: (): Promise<InstitutionGroup> => api.get<InstitutionGroup>(`/api/institution-groups/${id}/`)
});
}

export function useInstitutionGroupMutation() {
const queryClient = useQueryClient();
return useMutation({
mutationKey: ["institutionGroup", <{id}>],
mutationFn: ({ id, phoneNumbers }) =>
api.patch<InstitutionGroup>(`/api/institution-groups/${id}/`, { phoneNumbers }),
});
}
How do I include a variable in my mutationKey that my mutationFunction uses? In the root of my project, I want to do:
const queryClient = new QueryClient({
mutationCache: new MutationCache({
onSuccess: (_data, _variables, _context, mutation) => {
queryClient.invalidateQueries({
queryKey: mutation.options.mutationKey,
});
},
}),
});
const queryClient = new QueryClient({
mutationCache: new MutationCache({
onSuccess: (_data, _variables, _context, mutation) => {
queryClient.invalidateQueries({
queryKey: mutation.options.mutationKey,
});
},
}),
});
Automatic Query Invalidation after Mutations
Even though there is nothing built into React Query, it doesn't need a lot of code to implement automatic query invalidation in user-land thanks to the global cache callbacks.
14 Replies
aware-green
aware-greenOP9mo ago
I specifically want to use id which I reference in my mutationFn Or maybe there is an alternative pattern to globally set query invalidation during mutations where I am able to specify a mix of static strings and params I ingest in my mutation function?
xenial-black
xenial-black9mo ago
Not sure I follow, it looks like you have id already. predicate might be useful for you here
xenial-black
xenial-black9mo ago
Filters | TanStack Query React Docs
Some methods within TanStack Query accept a QueryFilters or MutationFilters object. Query Filters A query filter is an object with certain conditions to match a query with: tsx // Cancel all queries a...
aware-green
aware-greenOP9mo ago
simplified my code a little bit, I don't believe predicate will give me access to the variables passed into the mutationFn
xenial-black
xenial-black9mo ago
It does
aware-green
aware-greenOP9mo ago
I guess the only issue is then in my actual mutation cache I would have to have a predicate that I pass into invalidateQueries and customize the filtering based on the current mutationKey and what parameters I need to filter and do that for every mutation in my app. At that point I might as well specify an onSuccess locally in the useMutate call instead of as a global "default" btw updated my code a bit more to show the useQuery hook I want to invalidate that relies on <id>
xenial-black
xenial-black9mo ago
Yeah by not giving id to useInstitutionGroupMutation you're complicating it
aware-green
aware-greenOP9mo ago
yeah, so wondering if there's another pattern to achieve what I want where I can store the variables that my mutation function is called with to reference later. I even considered the meta field but that doesn't have access to the variables
xenial-black
xenial-black9mo ago
Not sure there is one. I think you'd have to finagle your variables with a predicate somehow You technically can put whatever you want into variables so you could do:
mutate({
id: 123
theRealMutationKey: [..., 123]
})
mutate({
id: 123
theRealMutationKey: [..., 123]
})
Ugly so I don't recommend it, but it's a solution I suppose
aware-green
aware-greenOP9mo ago
oh yeah that feels pretty hacky too At that point, yeah I would just not set a global onSuccess query invalidation and just do it every time I declare a useMutation. But since tkDodo wrote the article, wanted his opinion on this
xenial-black
xenial-black9mo ago
My guess is he would say pass id into your hook This actually reminds me of another thread Dominik responded to awhile ago. Someone was attempting to pass a hook into a child component where variables were accessible, trying to use "one hook", when the correct approach was to simply move the hook into the child component so there was one for each entity. I wonder if a simple restructure will help you since it seems like you're trying this "one hook" approach.
aware-green
aware-greenOP9mo ago
yeah could be valid. I think passing id probably the most straightforward solution and have each component ingesting it essentially creating a new instance of the useMutation hook.
extended-salmon
extended-salmon9mo ago
Yes.
aware-green
aware-greenOP9mo ago
Haha okay thanks

Did you find this page helpful?