В TanStack Router механизм отображения loader’ов позволяет асинхронно подгружать данные перед рендерингом компонента маршрута. Часто возникает необходимость контролировать момент показа индикатора загрузки, чтобы избежать мерцаний интерфейса при быстром получении данных. TanStack Router предоставляет гибкие возможности для настройки таких задержек.
Проблема появляется, когда асинхронная операция выполняется слишком быстро. Если loader показывается мгновенно, пользователь видит кратковременный всплеск индикатора, что создает ощущение “дерганного” интерфейса. Для решения этой проблемы применяются:
В TanStack Router для маршрута можно определить функцию
loader и настроить поведение через дополнительные
параметры. Основная логика заключается в применении обёртки с
таймерами.
import { createRouter, createRoute } from '@tanstack/router';
const userRoute = createRoute({
path: '/user/:id',
loader: async ({ params }) => {
const minDelay = 300; // минимальная задержка перед показом loader'а в мс
const startTime = Date.now();
const data = await fetchUserData(params.id);
const elapsed = Date.now() - startTime;
if (elapsed < minDelay) {
await new Promise(resolve => setTimeout(resolve, minDelay - elapsed));
}
return data;
},
});
Пояснение ключевых моментов:
startTime фиксирует момент начала запроса.elapsed определяет фактическое время
выполнения.minDelay), используется setTimeout для
искусственного удлинения времени загрузки.TanStack Router поддерживает хуки и утилиты для глобального контроля состояния загрузки:
useIsFetching() – возвращает булево
значение, если в данный момент выполняются какие-либо загрузки.useTransition() – позволяет создавать
кастомные переходы с задержкой отображения индикатора.Suspense – можно комбинировать с React
Suspense для плавного появления loader’ов с минимальной задержкой.Пример использования Suspense с задержкой:
import { Suspense } from 'react';
function DelayedLoader({ delay = 300 }) {
const [show, setShow] = React.useState(false);
React.useEffect(() => {
const timer = setTimeout(() => setShow(true), delay);
return () => clearTimeout(timer);
}, [delay]);
return show ? Загрузка... : null;
}
function UserPage() {
return (
}>
);
}
Здесь DelayedLoader гарантирует, что индикатор
не появится мгновенно, если данные подгружаются быстрее
установленной задержки.
TanStack Router интегрируется с кешем данных. Если данные уже загружены, loader может не отображаться вовсе. Для этого важно проверять состояние кеша перед вызовом задержки:
const loader = async ({ params, context }) => {
const cached = context.cache.get(params.id);
if (cached) return cached;
const minDelay = 300;
const start = Date.now();
const data = await fetchUserData(params.id);
const elapsed = Date.now() - start;
if (elapsed < minDelay) {
await new Promise(resolve => setTimeout(resolve, minDelay - elapsed));
}
context.cache.set(params.id, data);
return data;
};
Такой подход уменьшает лишние показы loader’ов, ускоряет пользовательский опыт и делает интерфейс более плавным.