T
TanStack•2y ago
genetic-orange

`invalidateQueries` only triggers re-fetch once after reload but not afterwards

I have a table that shows data. There's an edit button for each row that opens a dialog where you can update the data of the respective row. This triggers a mutation that will invalidateQueries onSuccess and the dialog will be closed. For the first time after reloading this also re-fetches the query connected to the table after invalidation. After that, when I edit data again, nothing happens. How can that be and how to fix it? UPDATE: The source problem (I think) is that I set the queryClient within the function body because showNotification is used with is returned from a custom hook. I would like to keep this solution but do not know how
4 Replies
genetic-orange
genetic-orangeOP•2y ago
The same actually also happens when I use refetchQueries instead 🤔
export const useUpdateNotification = () => {
const queryClient = useQueryClient();
// const { showSuccessNotification } = useSuccessfulMutation();
return useMutation<{ message?: string }, ApiError, TUseUpdateNotification>({
mutationFn: (args: TUseUpdateNotification) =>
DefaultService.postAdminMenuNotification(args),
onSuccess: async (data) => {
// showSuccessNotification(data);
console.log("invalidate", fetchAdminMenuNotification.all().queryKey);
await queryClient.refetchQueries({
queryKey: fetchAdminMenuNotification.all().queryKey,
});
},
});
};
export const useUpdateNotification = () => {
const queryClient = useQueryClient();
// const { showSuccessNotification } = useSuccessfulMutation();
return useMutation<{ message?: string }, ApiError, TUseUpdateNotification>({
mutationFn: (args: TUseUpdateNotification) =>
DefaultService.postAdminMenuNotification(args),
onSuccess: async (data) => {
// showSuccessNotification(data);
console.log("invalidate", fetchAdminMenuNotification.all().queryKey);
await queryClient.refetchQueries({
queryKey: fetchAdminMenuNotification.all().queryKey,
});
},
});
};
Ok figured out that the problem is the showSuccessNotification. But why?
const { showNotification } = useNotification();
// Create a client
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
mutations: {
onError: (error) => {
console.log(error);
if (error instanceof ApiError) {
showNotification({ severity: "error", error });
}
},
},
},
});
const { showNotification } = useNotification();
// Create a client
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
mutations: {
onError: (error) => {
console.log(error);
if (error instanceof ApiError) {
showNotification({ severity: "error", error });
}
},
},
},
});
Ok figured out it's probably because this queryClient is in a functions body so that it can use showNotification. Anyway this can be solved? POSSIBLE SOLUTION:
const { showNotification } = useNotification();

// Create a client
const queryClient = useMemo(
() =>
new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
mutations: {
onError: (error) => {
if (error instanceof ApiError) {
showNotification({ severity: "error", error });
}
},
},
},
}),
[showNotification],
);
const { showNotification } = useNotification();

// Create a client
const queryClient = useMemo(
() =>
new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
mutations: {
onError: (error) => {
if (error instanceof ApiError) {
showNotification({ severity: "error", error });
}
},
},
},
}),
[showNotification],
);
Wrapping QueryClient in a useMemo works so it won't be recreated if it didn't change. If that is good practice is another thing. Very happing for any suggestions!
tame-yellow
tame-yellow•2y ago
memo doesn't make it stable - useState for it
tame-yellow
tame-yellow•2y ago
useState for one-time initializations
Why you shouldn't rely on useMemo for guaranteed referential stability but prefer useState instead
genetic-orange
genetic-orangeOP•2y ago
Thank you very much @TkDodo 🔮 you're the best!

Did you find this page helpful?