T
TanStack6mo ago
foreign-sapphire

Is it possible to wait for a few seconds before invalidates the cache in onSuccess?

I have tried this, but it does not work as I expect
useMutation({
mutationFn: fetchData,
onSuccess: async () => {
await sleep(3000);
return queryClient.invalidateQueries({
queryKey: ["users", id],
});
},
});
useMutation({
mutationFn: fetchData,
onSuccess: async () => {
await sleep(3000);
return queryClient.invalidateQueries({
queryKey: ["users", id],
});
},
});
7 Replies
equal-aqua
equal-aqua6mo ago
What do you expect? What is happening?
foreign-sapphire
foreign-sapphireOP6mo ago
I'm trying to upload a file. When I upload success and immediately invalidate the cache. It seems like the upload process is not done on the server, so I can not get the latest content. I want to wait a few seconds before invalidating the cache This works, but I want to keep the loading state while waiting
useMutation({
mutationFn: fetchData,
onSuccess: () => {
setTimeout(() => {
queryClient.invalidateQueries({
queryKey: ["users", id],
});
}, 3000);
},
});
useMutation({
mutationFn: fetchData,
onSuccess: () => {
setTimeout(() => {
queryClient.invalidateQueries({
queryKey: ["users", id],
});
}, 3000);
},
});
automatic-azure
automatic-azure6mo ago
If you want to retain loading state, you need the mutationFn to still be running. The easiest way to do this is to simply put your sleep in your mutationFn, which will cause it to take longer
useMutation({
mutationFn: async (data) => {
const result = await myMutationFn(data);
await sleep(3000);
return result;
}
})
useMutation({
mutationFn: async (data) => {
const result = await myMutationFn(data);
await sleep(3000);
return result;
}
})
Personally, I think of the callbacks on useMutation less like .then(...), .catch(...), .finally(...), and more like .addEventListener("success", ...), .addEventListener("error", ...), .addEventListener("settled", ...), Alternatively, if you are submitting inside a form, my general advice to my team members is to always use mutateAsync, because the form will handle the loading state rather than the mutation. For example:
const handleSubmit = async (formData) => {
const result = await mutateAsync();
await sleep(3000);
invalidate();
}
const handleSubmit = async (formData) => {
const result = await mutateAsync();
await sleep(3000);
invalidate();
}
This way the form will typically remain loading while you are doing the extra work. If you are not using a form, this can be ignored
foreign-sapphire
foreign-sapphireOP6mo ago
Great! It works as I expect. Thanks
optimistic-gold
optimistic-gold6mo ago
It seems like the upload process is not done on the server
the server should likely not return unless it's done with the upload then?
foreign-sapphire
foreign-sapphireOP6mo ago
I'm not sure, but I think it still works properly, doesn't it? Because the process is not done, when I call api to get the content, it will return the current content
crude-lavender
crude-lavender6mo ago
Isn't it also possible that your original source of truth (useQuery) is revalidated due to expired cache/TTL or some other action, for example: window focus.

Did you find this page helpful?