T
TanStack3y ago
continuing-cyan

Old Value is rendered for a split second after mutation

I am switching an application from SWR to react-query and stumbled over this issue. When I try to implement optimistic updates, the old value is still rendered for a split second before the new value appears. I did not encounter this issue in equivalent SWR code. I have reproduced the issue in a minimal Codesandbox: https://codesandbox.io/s/distracted-cohen-nm8m4k It is not easy to spot the issue in such a minimal example as it renders very quickly, which is why also added timestamped console.logs. It becomes quite noticeable in a real-world example. Click on the name, enter a new name and press Enter. In the React-Query example, the old name is still rendered once before it picks up the new name. (again, if you cannot see it, check the console). The SWR example works as I would expect.
3 Replies
continuing-cyan
continuing-cyanOP3y ago
It works the way I want if I avoid useMutation:
function onSubmit(event) {
event.preventDefault();
event.stopPropagation();
__user = event.target.elements.user.value;
queryClient.setQueryData(["user"], __user);
setIsEditing(false);
}
function onSubmit(event) {
event.preventDefault();
event.stopPropagation();
__user = event.target.elements.user.value;
queryClient.setQueryData(["user"], __user);
setIsEditing(false);
}
But that's not ideal since I would have to implement default error handling here. (assuming I actually talk to an API as opposed to just setting a local variable)
foreign-sapphire
foreign-sapphire3y ago
You're expecting a global variable change to trigger a rerender?
continuing-cyan
continuing-cyanOP3y ago
No, I'm expecting the mutation to trigger a rerender. Which it does, but there's one rerender too many Hm, I think I got it. Use onMutate instead of onSuccess in the useMutation hook:
const updateUser = useMutation({
mutationFn: (newUser) => (__user = newUser),
onMutate: (newUser) => queryClient.setQueryData(["user"], newUser)
});
const updateUser = useMutation({
mutationFn: (newUser) => (__user = newUser),
onMutate: (newUser) => queryClient.setQueryData(["user"], newUser)
});
Then use onSuccess of the mutate function:
function onSubmit(event) {
event.preventDefault();
event.stopPropagation();
updateUser.mutate(event.target.elements.user.value, { onSuccess: () => setIsEditing(false)});

}
function onSubmit(event) {
event.preventDefault();
event.stopPropagation();
updateUser.mutate(event.target.elements.user.value, { onSuccess: () => setIsEditing(false)});

}

Did you find this page helpful?