RTK Query изначально спроектирован как слой управления серверным состоянием, а не как полноценный realtime-клиент, однако он учитывает нестабильность сети и умеет корректно реагировать на разрывы соединения. Обработка переподключений в контексте RTK Query включает несколько уровней: повторные HTTP-запросы, восстановление подписок, рефетч данных и интеграцию с пользовательской логикой через middleware и lifecycle-хуки.
Ключевой принцип заключается в том, что RTK Query не поддерживает «магическое» постоянное соединение, но предоставляет инструменты для построения устойчивого поведения поверх обычных запросов.
Потеря соединения может происходить в разных формах:
RTK Query рассматривает все эти ситуации как ошибки запроса, которые
могут быть обработаны через стандартный механизм
baseQuery.
RTK Query предоставляет утилиту retry из
@reduxjs/toolkit/query/react, которая добавляет
автоматические повторные попытки к baseQuery.
import { createApi, fetchBaseQuery, retry } from '@reduxjs/toolkit/query/react';
const baseQuery = retry(
fetchBaseQuery({
baseUrl: '/api',
}),
{
maxRetries: 3,
}
);
retryConditionНе все ошибки должны приводить к повторным запросам. Например,
400 Bad Request или 404 Not Found не являются
сетевыми сбоями.
const baseQuery = retry(
fetchBaseQuery({ baseUrl: '/api' }),
{
maxRetries: 2,
retryCondition: (error) => {
return (
error.status === 'FETCH_ERROR' ||
error.status === 'TIMEOUT_ERROR' ||
error.status >= 500
);
},
}
);
Здесь важно разделять:
Когда соединение восстанавливается, RTK Query сам по себе не «знает» об этом событии. Однако встроенный механизм подписок и refetching позволяет реализовать автоматическое восстановление данных.
Ключевые триггеры:
RTK Query поддерживает автоматический refetch при возвращении онлайн-статуса.
export const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
refetchOnReconnect: true,
endpoints: (builder) => ({
getUsers: builder.query({
query: () => 'users',
}),
}),
});
refetchOnReconnectwindow.online событиеХотя это не напрямую связано с переподключением, в реальных приложениях часто используется вместе:
export const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
refetchOnFocus: true,
});
Сценарий:
RTK Query использует систему подписок на кешированные данные. При разрыве соединения подписка не уничтожается, но может стать «устаревшей».
При восстановлении сети активные подписки могут инициировать повторную загрузку данных.
Для более сложных сценариев используется middleware на уровне Redux.
const reconnectMiddleware = (api) => (next) => (action) => {
if (action.type === 'network/reconnected') {
api.util.invalidateTags(['User', 'Post']);
}
return next(action);
};
После переподключения часто требуется:
RTK Query не управляет WebSocket напрямую, но интеграция возможна
через onCacheEntryAdded.
getMessages: builder.query({
query: () => 'messages',
async onCacheEntryAdded(
arg,
{ updateCachedData, cacheDataLoaded, cacheEntryRemoved }
) {
const ws = new WebSocket('wss://example.com');
try {
await cacheDataLoaded;
ws.onmess age = (event) => {
const data = JSON.parse(event.data);
updateCachedData((draft) => {
draft.push(data);
});
};
} catch {
ws.close();
}
await cacheEntryRemoved;
ws.close();
},
});
RTK Query не восстанавливает WebSocket автоматически. Обычно применяется внешняя логика:
oncloseinvalidateTagsДля стабильных приложений используется стратегия экспоненциальной задержки:
RTK Query через retry реализует аналогичную модель для
HTTP-запросов, но WebSocket требует ручной реализации.
RTK Query предоставляет hooks для контроля поведения:
onQueryStartedonCacheEntryAddedonQueryFulfilledПример ручного retry:
getData: builder.query({
query: () => '/data',
async onQueryStarted(arg, { dispatch, queryFulfilled }) {
try {
await queryFulfilled;
} catch (err) {
setTimeout(() => {
dispatch(api.endpoints.getData.initiate(arg));
}, 2000);
}
},
});
Этот подход используется, когда стандартный retry
недостаточен.
Кэш RTK Query остаётся в памяти Redux Store и не сбрасывается при потере соединения.
Важно учитывать:
refetchOnReconnectkeepUnusedDataFor влияет на срок жизни кешаВ реальных приложениях обработка переподключений строится на комбинации:
retry для HTTP ошибокrefetchOnReconnect для восстановления данныхinvalidateTags для принудительной синхронизацииrefetchOnReconnectНесмотря на встроенные механизмы, RTK Query не решает:
Эти задачи требуют дополнительного слоя архитектуры поверх RTK Query.
В зрелых приложениях слой работы с переподключениями обычно включает:
RTK Query в этой структуре выступает как слой синхронизации серверного состояния после восстановления соединения.