Методы setQueryData и getQueryData являются
частью объекта QueryClient и используются для прямой работы
с кешем TanStack Query без выполнения сетевых запросов.
Они позволяют:
Оба метода работают напрямую с Query Cache и используют
queryKey для поиска нужного запроса.
Метод getQueryData извлекает данные конкретного запроса
из кеша.
Синтаксис:
const data = queryClient.getQueryData(queryKey)
Пример:
const user = queryClient.getQueryData(['user', 5])
console.log(user)
Если запрос присутствует в кеше — метод вернёт данные.
Если данных нет — будет возвращён undefined.
TanStack Query хранит все запросы внутри внутреннего Query Cache.
Каждый запрос идентифицируется по queryKey.
Например:
['posts']
или:
['user', 15]
Метод ищет точное совпадение ключа и возвращает сохранённое значение.
Главное преимущество getQueryData — отсутствие сетевого
запроса.
Например:
const cachedPosts = queryClient.getQueryData(['posts'])
Здесь:
fetch;queryFn;Это особенно важно для:
const posts = useQuery({
queryKey: ['posts'],
queryFn: fetchPosts
})
После успешной загрузки:
const cachedPosts = queryClient.getQueryData(['posts'])
вернёт:
[
{
id: 1,
title: 'Post 1'
},
{
id: 2,
title: 'Post 2'
}
]
Частый сценарий:
const cachedUser = queryClient.getQueryData(['user', userId])
if (cachedUser) {
return cachedUser
}
Такой подход позволяет:
После выполнения мутации часто требуется получить текущее состояние кеша.
Пример:
const previousTodos = queryClient.getQueryData(['todos'])
Это особенно полезно для rollback при optimistic updates.
const mutation = useMutation({
mutationFn: updateTodo,
onMutate: async (newTodo) => {
await queryClient.cancelQueries({
queryKey: ['todos']
})
const previousTodos =
queryClient.getQueryData(['todos'])
return { previousTodos }
}
})
Здесь:
Метод работает не только внутри компонентов.
Например:
const user = queryClient.getQueryData(['auth'])
можно вызывать:
Метод setQueryData изменяет данные в кеше вручную.
Синтаксис:
queryClient.setQueryData(queryKey, data)
Пример:
queryClient.setQueryData(
['user', 5],
{
id: 5,
name: 'Alex'
}
)
После вызова:
Метод:
queryKey;Если запроса ещё нет — TanStack Query создаст его в кеше.
Даже без useQuery можно записать данные:
queryClient.setQueryData(
['settings'],
{
theme: 'dark'
}
)
После этого:
const settings =
queryClient.getQueryData(['settings'])
вернёт:
{
theme: 'dark'
}
Один из самых распространённых сценариев.
Обычно после мутации выполняется:
queryClient.invalidateQueries({
queryKey: ['todos']
})
Это запускает новый запрос.
Можно обновить кеш мгновенно:
queryClient.setQueryData(
['todos'],
(oldData) => {
return [
...oldData,
newTodo
]
}
)
Преимущества:
Метод поддерживает updater-функцию.
Синтаксис:
queryClient.setQueryData(
queryKey,
(oldData) => newData
)
Пример:
queryClient.setQueryData(
['counter'],
(old) => old + 1
)
TanStack Query передаст текущее значение кеша в old.
Неправильно:
queryClient.setQueryData(
['todos'],
[...todos, newTodo]
)
Проблема:
todos может быть устаревшим;Безопаснее:
queryClient.setQueryData(
['todos'],
(old = []) => {
return [...old, newTodo]
}
)
Пример:
queryClient.setQueryData(
['todos'],
(oldTodos) => {
return oldTodos.map((todo) => {
if (todo.id === updatedTodo.id) {
return updatedTodo
}
return todo
})
}
)
Такой подход позволяет:
queryClient.setQueryData(
['todos'],
(oldTodos) => {
return oldTodos.filter(
(todo) => todo.id !== deletedId
)
}
)
queryClient.setQueryData(
['profile'],
(oldProfile) => {
return {
...oldProfile,
avatar: newAvatar
}
}
)
Если кеш отсутствует:
const data =
queryClient.getQueryData(['todos'])
вернёт:
undefined
Поэтому важно учитывать этот случай:
queryClient.setQueryData(
['todos'],
(old = []) => {
return [...old, newTodo]
}
)
TanStack Query ожидает иммутабельное обновление.
Неправильно:
queryClient.setQueryData(
['todos'],
(oldTodos) => {
oldTodos.push(newTodo)
return oldTodos
}
)
Проблемы:
Правильно:
queryClient.setQueryData(
['todos'],
(oldTodos = []) => {
return [...oldTodos, newTodo]
}
)
Это один из ключевых сценариев.
Пример:
const mutation = useMutation({
mutationFn: addTodo,
onMutate: async (newTodo) => {
await queryClient.cancelQueries({
queryKey: ['todos']
})
const previousTodos =
queryClient.getQueryData(['todos'])
queryClient.setQueryData(
['todos'],
(old = []) => {
return [...old, newTodo]
}
)
return { previousTodos }
},
onError: (error, newTodo, context) => {
queryClient.setQueryData(
['todos'],
context.previousTodos
)
},
onSettled: () => {
queryClient.invalidateQueries({
queryKey: ['todos']
})
}
})
Последовательность работы:
Методы часто используются вместе.
Используется для:
Используется для:
Частая схема:
queryClient.setQueryData(
['post', id],
updatedPost
)
queryClient.invalidateQueries({
queryKey: ['post', id]
})
Сначала интерфейс обновляется мгновенно, затем сервер подтверждает актуальные данные.
queryFn;Допустим, список пользователей уже загружен:
['users']
При переходе на страницу пользователя можно заранее записать данные:
queryClient.setQueryData(
['user', user.id],
user
)
Тогда детальная страница:
useQuery({
queryKey: ['user', userId],
queryFn: fetchUser
})
сразу покажет кешированные данные.
Частый сценарий:
queryClient.setQueryData(
['post', post.id],
post
)
Это позволяет:
Пример сложного обновления:
queryClient.setQueryData(
['posts'],
(oldPosts = []) => {
return oldPosts.map((post) => {
if (post.id !== postId) {
return post
}
return {
...post,
comments: [
...post.comments,
newComment
]
}
})
}
)
setQueryData обновляет только подписанные запросы.
TanStack Query:
Поэтому иммутабельность критически важна.
Плохо:
oldUser.name = 'John'
return oldUser
Плохо:
return [...old, item]
Если old === undefined, приложение упадёт.
Плохо:
setQueryData(['todos'], todos)
Лучше:
setQueryData(
['todos'],
(old) => old
)
Метод подходит для:
Метод подходит для: