Optimistic update cập nhật UI ngay khi user thao tác, chưa đợi API xác nhận, và rollback nếu API fail.
ts
useMutation({
mutationFn: addTodo,
onMutate: async (newTodo) => {
await queryClient.cancelQueries({ queryKey: ['todos'] })
const snapshot = queryClient.getQueryData(['todos'])
queryClient.setQueryData(['todos'], (old) => [
...old,
{ ...newTodo, id: 'temp-' + Date.now() },
])
return { snapshot }
},
onError: (err, newTodo, context) => {
queryClient.setQueryData(['todos'], context.snapshot)
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['todos'] })
},
})cancelQueriesphải chạy trước khi ghi optimistic — nếu không, một lần refetch nền có thể ghi đè state vừa đặt.- Giá trị
onMutatetrả về chính làcontexttrongonError/onSettled. - Dùng optimistic cho action user mong phản hồi tức thì (like, follow, toggle); còn thanh toán hay tạo đơn thì invalidate thường tốt hơn, vì rollback khó chịu hơn một chút loading.
Lưu ý: ID tạm ('temp-123') phải được thay bằng ID thật sau khi server xác nhận — đó là lý do onSettled invalidate để refetch data thật.