В RTK Query кэширование не ограничивается простым хранением данных в памяти. Каждый фрагмент состояния запроса существует в рамках управляемого жизненного цикла, который определяет, как долго данные остаются актуальными, когда они считаются устаревшими и в какой момент могут быть удалены из хранилища.
Ключевая особенность механизма заключается в том, что кэш привязан не только к данным, но и к подпискам на них. Это означает, что время жизни кэша определяется сочетанием активности компонентов, настроек API-сервиса и внутренних таймеров библиотеки.
keepUnusedDataForГлавный параметр управления временем жизни кэша —
keepUnusedDataFor. Он задаётся на уровне API-сервиса или
для конкретного endpoint.
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const api = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
keepUnusedDataFor: 60,
endpoints: (builder) => ({
getPosts: builder.query({
query: () => '/posts',
}),
}),
});
Значение задаётся в секундах и определяет, как долго данные остаются в кэше после того, как последний подписчик был удалён.
Ключевая логика:
Каждый вызов useQuery создаёт подписку на конкретный
cache key. RTK Query группирует запросы по следующим признакам:
Это означает, что разные компоненты могут использовать один и тот же кэш, если аргументы совпадают.
const { data } = useGetPostsQuery();
const { data } = useGetPostsQuery();
Обе подписки используют один и тот же cache entry.
Пока хотя бы одна подписка активна:
keepUnusedDataFor не запускаетсяПосле исчезновения последней подписки:
RTK Query тесно связан с жизненным циклом React-компонентов. При размонтировании компонента:
Пример сценария:
useGetPostsQuerykeepUnusedDataForВажно различать два независимых механизма:
Определяет, когда данные будут удалены из store.
Определяет, когда данные считаются устаревшими и требуют обновления.
RTK Query не удаляет кэш автоматически при устаревании. Вместо этого он может инициировать refetch при определённых условиях.
refetchOnMount
и его влияние на кэшПараметр refetchOnMount управляет тем, будет ли запрос
повторно выполнен при повторном монтировании компонента.
useGetPostsQuery(undefined, {
refetchOnMountOrArgChange: true,
});
Даже если кэш ещё существует:
Это не влияет напрямую на время жизни кэша, но влияет на его обновление.
В createApi можно задать базовое значение:
keepUnusedDataFor: 30
Это значение применяется ко всем endpoint, если не переопределено локально.
Локальное значение имеет приоритет:
getPosts: builder.query({
query: () => '/posts',
keepUnusedDataFor: 120,
})
keepUnusedDataFor никогда не запускаетсяRTK Query позволяет управлять временем жизни кэша через invalidateTags и resetApiState.
resetApiStateПолная очистка состояния API:
dispatch(api.util.resetApiState());
После вызова:
Инвалидация тегов не удаляет данные сразу. Она помечает их как устаревшие.
invalidatesTags: ['Posts']
После инвалидации:
После исчезновения последнего подписчика RTK Query:
фиксирует timestamp освобождения
запускает внутренний таймер
по истечении keepUnusedDataFor:
Если до истечения таймера появляется новая подписка:
При частом монтировании и размонтировании компонентов:
keepUnusedDataFor приводит к
постоянным повторным запросамДанные можно условно разделить:
RTK Query оптимизирует работу за счёт удержания кэша в памяти. Время жизни напрямую влияет на:
Длинный жизненный цикл кэша уменьшает количество запросов, но увеличивает вероятность устаревших данных. Короткий цикл повышает актуальность, но снижает эффективность кеширования.
Каждая комбинация аргументов создаёт отдельный cache key.
useGetPostsQuery({ page: 1 });
useGetPostsQuery({ page: 2 });
Это означает:
Удаление одного не влияет на другой.
Механизм очистки кэша работает как специализированный garbage collector:
Основное отличие от классического GC заключается в том, что он привязан к бизнес-логике запросов, а не к объектам JavaScript напрямую.