useMutation cung cấp 4 lifecycle callbacks, có thể set ở cả mutation level và per-mutate() call level (per-call override mutation level). onMutate(variables): chạy synchronously trước khi mutation request gửi đi — dùng để optimistic update cache, return value trở thành context trong onError/onSettled.
- Nếu return Promise, mutation chờ resolve.
onSuccess(data, variables, context): chạy khi API thành công với response data — thường dùng để invalidate related queries:queryClient.invalidateQueries({ queryKey: ['todos'] })hoặc setQueryData với response.onError(error, variables, context): chạy khi API fail — context từ onMutate dùng để rollback:queryClient.setQueryData(['todos'], context.previousTodos).onSettled(data, error, variables, context): luôn chạy sau onSuccess hoặc onError (như finally) — an toàn để invalidate queries ở đây vì chạy cả khi success lẫn error. - Thứ tự: onMutate → [mutationFn] → onSuccess/onError → onSettled.
Pitfall: nếu cả mutation-level và call-level đều có onSuccess, cả hai đều chạy — mutation-level chạy trước.