An undoable update is the version of an optimistic update where the actual mutation for the update is executed after a certain amount of time so that the mutation can be undone in that period of time.
Key factor is that mutation function for the useMutation needs to return a promise. We return a promise where the actual mutation function(fetch e.g. ) is executed in a timeout and the promise that we return is resolved when the mutation function is resolved.
Undoing the mutation requires to cancel the timeout and the promise to be rejected so that the previous state of the query is recovered via onError.
The function to cancel the mutation is made accessible for a cancel button by holding it in a ref.
There are plenty opportunities to improve upon like managing various states along the flow of undoing an update or integrating with a notification system. I hope this was helpful.