В каких случаях нужен рефетч данных после удаления, а в каких можно обойтись без него
Что проверяют
Умеете ли вы думать о клиентском кэше как о копии серверного состояния и понимать, какая её часть устарела после изменения. Следом часто спрашивают про оптимистичное удаление и откат при ошибке.
Как отвечать
Критерий простой: можно ли на клиенте точно вычислить новое состояние. Если можно, рефетч не нужен.
Без рефетча обходятся, когда:
- список загружен целиком: элемент убирают из кэша, в TanStack Query через
queryClient.setQueryData, в RTK Query черезupdateQueryData; - сервер вернул новое состояние: обновлённый список или счётчик кладут в кэш из ответа;
- удаление оптимистичное: элемент исчезает сразу в
onMutate, снимок старых данных сохраняется, вonErrorкэш откатывается.
Рефетч нужен, когда:
- список постраничный: на текущую страницу должен подтянуться элемент со следующей, меняется и общий
total; - сортировка, фильтры и агрегаты считаются на сервере: суммы, счётчики, рейтинги клиент надёжно не пересчитает;
- есть каскад: удаление проекта убирает его задачи и комментарии, и эти запросы тоже устарели;
- данные меняют другие пользователи: тут рефетч после своей мутации мало что даёт, нужна подписка или периодическое обновление.
Практичный компромисс: оптимистично убрать элемент, а в onSettled вызвать invalidateQueries({ queryKey: ["todos"] }). Интерфейс реагирует мгновенно, а кэш сверяется с сервером в фоне. В RTK Query ту же роль играют providesTags и invalidatesTags, в Next.js на сервере revalidatePath и revalidateTag.
Где спотыкаются
Инвалидируют всё подряд после каждой мутации. Приложение шлёт десяток лишних запросов, а список мигает.
Удаляют оптимистично без отката. Сервер ответил 403 или 500, а элемент пропал из интерфейса и вернётся только после перезагрузки.
Забывают про соседние кэши: карточку удалённой сущности, счётчик в шапке, бесконечную ленту. В ленте на offset удаление сдвигает выдачу, и при подгрузке следующей порции один элемент пропускается.