В основе работы RTK Query лежит система подписок (subscriptions),
которая связывает жизненный цикл запроса с компонентами приложения.
Каждый раз, когда используется useQuery или любой другой
query-хук, создаётся подписка на конкретный запрос в кэше. Эта подписка
управляет тем, когда данные должны быть запрошены, обновлены или
удалены.
Подписка в RTK Query — это не просто факт «компонент использует данные», а полноценный объект состояния, включающий:
При первом вызове:
const { data } = useGetUsersQuery();
RTK Query выполняет несколько шагов:
cache entry).Ключевой момент: каждая уникальная комбинация аргументов создаёт отдельную подписку. Например:
useGetUserQuery(1);
useGetUserQuery(2);
создают две независимые подписки.
Каждый компонент, использующий один и тот же запрос с одинаковыми аргументами, увеличивает счётчик подписок:
subscriptionCount + 1subscriptionCount - 1Когда счётчик достигает нуля, RTK Query не удаляет данные сразу, а запускает таймер удержания кэша.
Параметр keepUnusedDataFor определяет, сколько времени
данные остаются в кэше после того, как последняя подписка была
удалена.
createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
keepUnusedDataFor: 60,
endpoints: (builder) => ({
getUsers: builder.query({
query: () => '/users'
})
})
});
Поведение:
Если компонент повторно монтируется до истечения
keepUnusedDataFor, RTK Query:
Это позволяет избегать лишних сетевых запросов и ускоряет повторный рендер интерфейса.
Каждое изменение аргументов воспринимается как новая подписка:
useGetUserQuery(userId);
Если userId изменился:
Важно, что RTK Query не «перепривязывает» старую подписку, а полностью создаёт новую сущность.
Когда компонент перестаёт использовать данные:
function User() {
const { data } = useGetUserQuery(1);
return null;
}
при размонтировании:
Это поведение встроено в middleware RTK Query и не требует ручного управления.
Вся система подписок реализована через middleware RTK Query, которое:
query initiated;Store хранит структуру примерно следующего вида:
state.api.queries[endpointName][serializedArgs]
Каждая запись содержит:
status (pending / fulfilled / rejected);data;fulfilledTimeStamp;subscriptions (map активных подписчиков).Если компонент возвращается на экран:
useGetUsersQuery();
RTK Query:
Опция refetchOnMountOrArgChange влияет на поведение
подписок при повторном подключении:
useGetUsersQuery(undefined, {
refetchOnMountOrArgChange: true
});
Возможные режимы:
false — использовать кэш без обновления;true — всегда выполнять запрос при монтировании;number — считать данные устаревшими после времени.Эта настройка работает поверх системы подписок и не заменяет её.
RTK Query интегрируется с событиями браузера:
refetchOnFocus — обновление при возвращении
вкладки;refetchOnReconnect — обновление при восстановлении
сети.Система подписок участвует косвенно:
Подписка считается активной, пока:
useQuery используется с теми же аргументами;Пример отключения подписки:
useGetUserQuery(id, { skip: !id });
При skip: true:
skipToken используется для условного отключения
запроса:
import { skipToken } from '@reduxjs/toolkit/query';
useGetUserQuery(userId ?? skipToken);
Поведение:
skipToken, подписка не создаётся;subscriptions;RTK Query сериализует аргументы запроса. Подписка зависит не от ссылки объекта, а от результата сериализации:
useGetUserQuery({ id: 1 });
useGetUserQuery({ id: 1 });
обе строки создают одну подписку, так как сериализованный ключ совпадает.
Это критически важно для:
Когда:
keepUnusedDataFor;RTK Query:
Если позже снова запрашиваются те же данные:
Если несколько компонентов используют один endpoint:
<ComponentA /> → useGetUsersQuery()
<ComponentB /> → useGetUsersQuery()
RTK Query:
При удалении одного компонента:
Если последний подписчик удалён и затем появляется новый:
При использовании pollingInterval:
useGetUsersQuery(undefined, {
pollingInterval: 5000
});
подписка становится активным источником периодических запросов:
Логика RTK Query строится вокруг трёх базовых принципов:
Эта модель позволяет синхронизировать состояние UI с серверными данными без явного управления жизненным циклом запросов и без необходимости вручную отслеживать отписки.