Optimistic update flow đầy đủ: khi user thực hiện action, update UI ngay lập tức trước khi API confirm, rollback nếu API fail.
- Implementation:
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'] }) }. - Quan trọng:
cancelQueriestrước khi optimistic update — tránh race condition khi background refetch overwrite optimistic state. - Context pattern: onMutate return value trở thành
contexttrong onError/onSettled. - Khi nào dùng optimistic vs simple invalidation: optimistic cho actions user expect instant feedback (like, follow, toggle), simple invalidation cho actions phức tạp hơn (payment, create order) vì rollback UX tệ hơn là loading nhỏ.
Pitfall: optimistic ID ('temp-123') cần được replace bằng real ID sau khi server confirm — onSettled invalidate để refetch với real data.