Хук useQuery является базовым механизмом получения
данных в RTK Query и автоматически генерируется для каждого
query-endpoint, определённого в createApi. Его
основная задача — управлять жизненным циклом HTTP-запроса, кэшированием,
повторным использованием данных и состояниями загрузки без ручного
управления состоянием в Redux.
Каждый query-endpoint в API-сервисе автоматически
превращается в React-хук.
import { createApi, fetchBaseQuery } fr om '@reduxjs/toolkit/query/react';
export const api = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({
baseUrl: 'https://api.example.com',
}),
endpoints: (builder) => ({
getPosts: builder.query({
query: () => '/posts',
}),
}),
});
export const { useGetPostsQuery } = api;
В данном случае useGetPostsQuery создаётся автоматически
и привязывается к endpoint getPosts.
Хук вызывается внутри функционального компонента React и возвращает объект состояния запроса и сами данные.
import { useGetPostsQuery } from './api';
function PostsList() {
const { data, error, isLoading } = useGetPostsQuery();
if (isLoading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка загрузки</div>;
return (
<ul>
{data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
При первом рендере автоматически запускается запрос. Повторные рендеры используют кэшированные данные, если они уже есть.
useQuery принимает аргумент, который передаётся в
query-функцию endpoint.
getPostById: builder.query({
query: (id) => `/posts/${id}`,
});
Использование:
const { data } = useGetPostByIdQuery(5);
Аргумент влияет на ключ кэширования. RTK Query формирует уникальный cache key на основе endpoint и переданных параметров.
useQuery возвращает объект состояния запроса, включающий
ключевые поля:
data — результат запроса после успешного
выполненияerror — объект ошибки при неудачном запросеisLoading — первый запрос ещё выполняется, данных
нетisFetching — запрос выполняется (включая фоновые
обновления)isSuccess — запрос успешно завершёнisError — запрос завершён с ошибкойrefetch — функция ручного повторного запросаconst {
data,
error,
isLoading,
isFetching,
refetch,
} = useGetPostsQuery();
Различие между isLoading и isFetching
принципиально: isLoading относится к первичной загрузке,
тогда как isFetching отражает любое текущее получение
данных, включая рефетч.
RTK Query сохраняет результат запроса в store и повторно использует его при повторном обращении к тому же endpoint с теми же аргументами.
При наличии кэшированных данных:
RTK Query позволяет управлять поведением запроса через опции хука.
const { data } = useGetPostByIdQuery(id, {
skip: !id,
});
Если skip равен true, запрос не выполняется
и состояние не инициализируется.
const { data } = useGetPostsQuery(undefined, {
pollingInterval: 5000,
});
Запрос будет повторяться каждые 5 секунд, пока компонент смонтирован.
useGetPostsQuery(undefined, {
refetchOnMountOrArgChange: true,
});
Определяет, должен ли запрос выполняться при каждом монтировании компонента или изменении аргументов, даже если данные уже есть в кэше.
useGetPostsQuery(undefined, {
refetchOnFocus: true,
});
Активирует повторный запрос при возврате фокуса на вкладку браузера.
useGetPostsQuery(undefined, {
refetchOnReconnect: true,
});
Запускает повторный запрос при восстановлении сетевого соединения.
Аргумент запроса используется RTK Query для построения ключа кэша. Сериализация выполняется автоматически, но важно учитывать структуру данных.
useGetPostsQuery({ page: 1, lim it: 10 });
RTK Query интерпретирует объект как уникальный идентификатор запроса. Изменение порядка ключей объекта может повлиять на кэширование, поэтому рекомендуется использовать стабильные структуры данных.
Функция refetch инициирует принудительное обновление
данных независимо от кэша.
const { data, refetch } = useGetPostsQuery();
<button onCl ick={() => refetch()}>Обновить</button>;
При вызове выполняется новый запрос к серверу, а кэш обновляется.
Каждое изменение состояния запроса вызывает повторный рендер компонента. RTK Query оптимизирует обновления так, чтобы не выполнять лишние перерендеры при неизменных данных.
Основные сценарии:
isLoading = truedata заполняется,
isLoading = falseisFetching = true,
data сохраняетсяИзменение аргумента автоматически приводит к новому запросу.
const [page, setPage] = useState(1);
const { data } = useGetPostsQuery(page);
При изменении page RTK Query:
Часто запрос необходимо выполнять только при наличии валидных данных.
const userId = props.userId;
const { data } = useGetUserQuery(userId, {
skip: !userId,
});
Такой подход предотвращает выполнение лишних запросов и снижает нагрузку на сервер.
Если один и тот же endpoint используется в нескольких компонентах с одинаковыми аргументами, RTK Query:
Это позволяет строить глобально консистентное состояние без ручной синхронизации.
Перед выполнением запроса data равен
undefined, поэтому важно учитывать начальное состояние:
const { data = [] } = useGetPostsQuery();
Это позволяет избежать ошибок при работе с неинициализированными данными.
RTK Query интегрируется с событиями браузера и автоматически реагирует на изменения окружения:
refetchOnReconnectЕсли несколько компонентов подписаны на один и тот же query, обновление данных происходит централизованно через store:
При размонтировании компонента RTK Query не обязательно удаляет кэш сразу. Данные сохраняются в store до истечения времени или явной очистки, что позволяет повторно использовать их без запроса к серверу при следующем монтировании.