Перейти к содержимому

6. Query: инвалидация кэша

После мутации данные на сервере изменились, но TanStack Query не знает об этом. Инвалидация сообщает библиотеке: «эти данные устарели, нужно их обновить». При следующем обращении к кэшу автоматически выполнится новый запрос.

Самый распространённый способ обновить данные после мутации:

const queryClient = useQueryClient()
// Инвалидировать все запросы с ключом 'users'
queryClient.invalidateQueries({ queryKey: ['users'] })
// Инвалидировать конкретного пользователя
queryClient.invalidateQueries({ queryKey: ['user', userId] })
// Инвалидировать всё что начинается с 'user' (включая ['user', 1], ['users', 'list'])
queryClient.invalidateQueries({ queryKey: ['user'] })
// Инвалидировать ВСЕ запросы
queryClient.invalidateQueries()

TanStack Query использует иерархическое сопоставление ключей:

queryClient.invalidateQueries({ queryKey: ['users'] })
// Инвалидирует: ['users'], ['users', 1], ['users', { filter: 'active' }]
queryClient.invalidateQueries({ queryKey: ['users', 1] })
// Инвалидирует ТОЛЬКО: ['users', 1]
// НЕ инвалидирует: ['users'], ['users', 2]

refetchQueries немедленно запускает запрос, не дожидаясь обращения к кэшу:

// Принудительно обновить сейчас
await queryClient.refetchQueries({ queryKey: ['users'] })
// Только активные запросы (есть подписчики)
await queryClient.refetchQueries({ queryKey: ['users'], type: 'active' })

Позволяет напрямую установить данные в кэш без запроса. Ключевой инструмент для оптимистичных обновлений:

// Установить данные
queryClient.setQueryData(['user', 1], { id: 1, name: 'Новое имя' })
// Обновить данные (как setState с функцией)
queryClient.setQueryData(['users'], (oldData: User[]) => {
return oldData.map(user =>
user.id === updatedUser.id ? updatedUser : user
)
})
const users = queryClient.getQueryData<User[]>(['users'])
const user = queryClient.getQueryData<User>(['user', 1])

Полезно перед оптимистичным обновлением — отменяем текущий запрос, чтобы не перезаписать наши изменения:

await queryClient.cancelQueries({ queryKey: ['users'] })
queryClient.removeQueries({ queryKey: ['user', oldUserId] })