How do you handle concurrent optimistic updates without older responses overwriting newer data? #11408
|
I have multiple mutations updating the same query cache. For example, if a user quickly updates the same item twice: I update the cache optimistically in onMutate and invalidate the query in onSettled. The problem is that sometimes the first request finishes after the second one, and the older response/refetch can overwrite the latest state. What is the recommended way to handle this in TanStack Query? Should I cancel queries, track mutation versions, avoid invalidating after every mutation, or handle this some other way? |
Replies: 3 comments
|
If the same item can be mutated more than once, give the mutation a shared Keep the normal optimistic-update pattern in await queryClient.cancelQueries({ queryKey: ['item', id] })
const previous = queryClient.getQueryData(['item', id])
queryClient.setQueryData(['item', id], optimistic)
|
|
|
Hi @kuldeeprajput-dev . Combine the two approaches above — they solve different halves. scope.id serializes same-item writes so “pending” can’t overtake “done”. cancelQueries + snapshot/rollback + single invalidate handles the read side. Either alone still races. const mutation = useMutation({ Why: scope.id guarantees serial execution per item; cancelQueries stops a stale refetch from clobbering the optimistic write; the _v version (or server updatedAt) makes “older response overwrites newer” structurally impossible; the isMutating guard turns N rapid mutates into 1 invalidate instead of N refetch races; writing the server response via setQueryData avoids a refetch entirely when the server returns the row. Sources: |
filtershould filter for mutations you care aboutscope.idon your mutation. All mutations in the same scope are guaranteed run in serial.