TanStack Vue Query: мутации и optimistic updates
↑ 5.2 Состояние: Pinia, SSOT, Vue Query · ← Предыдущая
Зачем это на собесе
Как отправлять изменения и мгновенно обновлять UI с корректным откатом.
Объяснение
Мутация — операция изменения на сервере (POST/PUT/DELETE); в отличие от запроса, не кэшируется и запускается вручную.
const qc = useQueryClient();
const { mutate, mutateAsync, isPending, error } = useMutation({
mutationFn: (dto: UpdateOrder) => api.updateOrder(dto.id, dto),
onSuccess: (updated) => {
qc.setQueryData(["order", updated.id], updated); // точечно
qc.invalidateQueries({ queryKey: ["orders"] }); // список — перезапрос
notify("Сохранено");
},
onError: (e) => notify(errorMessage(e), "negative"),
onSettled: () => qc.invalidateQueries({ queryKey: ["orders"] }),
});
mutate(dto, { onSuccess: () => router.back() });Оптимистичное обновление: UI меняется сразу, откат при ошибке.
useMutation({
mutationFn: (id: number) => api.toggleFavorite(id),
onMutate: async (id) => {
await qc.cancelQueries({ queryKey: ["orders"] }); // отменить исходящие запросы, чтобы не затёрли
const previous = qc.getQueryData<Order[]>(["orders"]); // снимок для отката
qc.setQueryData<Order[]>(["orders"], (old) => old?.map(o => o.id === id ? { ...o, favorite: !o.favorite } : o));
return { previous };
},
onError: (_e, _id, ctx) => qc.setQueryData(["orders"], ctx?.previous), // откат
onSettled: () => qc.invalidateQueries({ queryKey: ["orders"] }), // синхронизация с сервером
});В новых версиях можно оптимистично показывать variables мутации прямо в UI (mutation.variables) без правки кэша.
Практики:
- Идемпотентность и
Idempotency-Keyдля повторов. - Блокировка кнопки на время
isPending, защита от двойного клика. - Последовательные мутации:
scope(очередь),mutateAsync+await. - Ошибки валидации сервера (422) → поля формы.
- Офлайн:
networkMode,persistQueryClient.
Нюансы и подводные камни
- Без
cancelQueriesфоновый запрос может перезаписать оптимистичное значение. - Откат должен восстанавливать именно снимок до изменений.
- Инвалидация в
onSettledгарантирует итоговую согласованность. - Оптимизм оправдан для частых и предсказуемых операций (лайк, чекбокс); для платежей — нет.
- Ключи кэша: обновляйте все затронутые (список, карточка).
Практика
- Реализуйте оптимистичное переключение статуса с откатом при ошибке.
- После создания заказа инвалидируйте список и перейдите на карточку.
- Защитите форму от повторной отправки.
Вопросы с ответами
Что такое optimistic update?
Мгновенное изменение UI до ответа сервера с откатом при ошибке.
Зачем
cancelQueriesвonMutate?Чтобы ответ фонового запроса не затёр оптимистичное значение.