New onQuery handler? #278
|
In some cases, we might want to optimistically update the cache before or at the same time, when the mutation occurs. We can do it by using queryCache.setQueryData('todos', [...data, text])
...
mutatePostTodo(text)But as I can see, we can't encapsulate an optimistic cache update into the custom hook. If we would have a handler, that executes at the same time as the mutation, we could do it: function useCustomDelete() {
return useMutation(foo, { onQuery: variables => queryCache.setQueryData(...)})
}
const [delete] = useCustomDelete();
...
delete(variables);What do you think? |
Replies: 5 comments 20 replies
|
Ooooooo very interesting. How about onMutate? |
|
Would it be worth discussing how a general rollback would take place too? Eg if the mutation falls? |
|
What do you think about this? Automatic Rollback for Failed MutationsWhen you optimistically update your state before performing a mutation, there is a non-zero chance that the mutation will fail. In that event, you would normally refetch your queries that you optimistically updated. In some circumstances though, refetching may not work correctly and the mutation error could represent some type of server issue that won't make it possible to refetch. In this event, you can instead choose to rollback your update. To do this, useMutation(updateTodo, {
onMutate: (newTodo) => {
// Store the previous value in this closure
const previousTodo = queryCache.getQueryData(['todos', newTodo.id])
// Optimistically update the query data
queryCache.setQueryData(['todos', newTodo.id], newTodo)
// Return a rollback function
return (err) => {
queryCache.setQueryData(['todos', newTodo.id], previousTodo)
}
}
}) |
Did you consider something like this? function useCustomDelete() {
const [mutate, ...mutation] = useMutation(foo);
function customMutate(...args) {
queryCache.setQueryData(...)
return mutate(...args)
}
return [customMutate, ...mutation];
}
const [delete] = useCustomDelete();
...
delete(variables); |
|
Here are the final docs: Automatic Rollback for Failed MutationsWhen you optimistically update your state before performing a mutation, there is a non-zero chance that the mutation will fail. In most cases, you can just trigger a refetch for your optimistic queries to revert them to their true server state. In some circumstances though, refetching may not work correctly and the mutation error could represent some type of server issue that won't make it possible to refetch. In this event, you can instead choose to rollback your update. To do this, useMutation(updateTodo, {
// When mutate is called:
onMutate: (newTodo) => {
// Snapshot the previous value
const previousTodo = queryCache.getQueryData(['todos', newTodo.id])
// Optimistically update to the new value
queryCache.setQueryData(['todos', newTodo.id], newTodo)
// Return the snapshotted value
return previousTodo
},
// If the mutation fails, use the value returned from onMutate to roll back
onError: (err, newTodo, previousTodo) => {
queryCache.setQueryData(['todos', newTodo.id], previousTodo)
}
// If the mutation was successful:
onSuccess: newTodo => {
queryCache.setQueryData(['todos', newTodo.id], newTodo)
}
})You can also use the useMutation(updateTodo, {
// ...
onSettled: (newTodo, error, variables, previousTodo) => {
if (error) {
queryCache.setQueryData(['todos', newTodo.id], previousTodo)
} else {
queryCache.setQueryData(['todos', newTodo.id], newTodo)
}
},
}) |
Here are the final docs:
Automatic Rollback for Failed Mutations
When you optimistically update your state before performing a mutation, there is a non-zero chance that the mutation will fail. In most cases, you can just trigger a refetch for your optimistic queries to revert them to their true server state. In some circumstances though, refetching may not work correctly and the mutation error could represent some type of server issue that won't make it possible to refetch. In this event, you can instead choose to rollback your update.
To do this,
useMutation'sonMutatehandler option allows you to return a snapshotted rollback value that will later be passed to bothonErrorandonSettled…