Fallback-компоненты — это специальные компоненты, которые отображаются в момент ожидания завершения асинхронных операций маршрута. Они особенно важны при работе с ленивой загрузкой данных или компонентов, когда рендеринг основного содержимого маршрута невозможен до получения необходимых данных.
В TanStack Router каждая маршрутизируемая точка может содержать
loader или component, возвращающий промис.
Если промис не завершён, рендеринг основного компонента блокируется. Для
решения этой проблемы используется свойство fallback, куда
передаётся компонент ожидания.
Пример базового использования:
import { Router, Route } from '@tanstack/router';
const Loading = () => <div>Загрузка...</div>;
const router = new Router({
routeTree: new Route({
path: '/',
component: HomePage,
loader: async () => {
const data = await fetchData();
return data;
},
fallback: <Loading />
})
});
Здесь Loading будет отображаться до завершения
loader.
TanStack Router поддерживает асинхронную загрузку компонентов. Для
этого используется динамический импорт с React.lazy и
Suspense. В сочетании с fallback это
обеспечивает плавный пользовательский опыт без “мёртвого экрана”.
Пример:
import React, { Suspense } from 'react';
import { Router, Route } from '@tanstack/router';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
const Loading = () => <div>Загрузка...</div>;
const router = new Router({
routeTree: new Route({
path: '/lazy',
component: () => (
<Suspense fallback={<Loading />}>
<LazyComponent />
</Suspense>
)
})
});
Использование Suspense позволяет централизовать
управление fallback-компонентами при динамических загрузках, что снижает
дублирование кода.
TanStack Router позволяет определять fallback не только для отдельных
маршрутов, но и для целых веток маршрутов. Если у родительского маршрута
задан fallback, он автоматически применяется ко всем
дочерним маршрутам, которые ещё не загрузились.
const Parent = new Route({
path: '/parent',
component: ParentComponent,
fallback: <ParentLoading />,
children: [
new Route({ path: 'child', component: ChildComponent }),
new Route({ path: 'child2', component: Child2Component }),
]
});
Здесь при переходе на /parent/child или
/parent/child2 будет отображён ParentLoading
до полной готовности дочерних компонентов.
Fallback-компоненты могут быть динамическими, с логикой изменения в зависимости от состояния загрузки данных. Например, можно показывать разные индикаторы в зависимости от типа запроса:
const DataFallback = ({ resourceType }) => {
if (resourceType === 'user') return <div>Загрузка данных пользователя...</div>;
if (resourceType === 'posts') return <div>Загрузка постов...</div>;
return <div>Загрузка...</div>;
};
const router = new Router({
routeTree: new Route({
path: '/dashboard',
component: Dashboard,
loader: async ({ context }) => await fetchDashboardData(context),
fallback: <DataFallback resourceType="dashboard" />
})
});
loaderloader в TanStack Router возвращает данные, которые
автоматически передаются компоненту через пропсы. Если
loader ещё не завершился, отображается fallback. После
завершения промиса происходит автоматический рендер основного компонента
с результатами loader.
Ключевые моменты:
Для приложений с большим количеством маршрутов имеет смысл определить
единый глобальный fallback через контекст или HOC. Например, создаётся
AppFallback и оборачивается в корневой маршрутизатор:
const AppFallback = () => <div>Приложение загружается...</div>;
const router = new Router({
routeTree: rootRoute,
defaultFallback: <AppFallback />
});
Все маршруты без собственного fallback будут
использовать AppFallback.
React.lazy и Suspense.Fallback-компоненты в TanStack Router обеспечивают гибкое и удобное управление состояниями загрузки, делают приложение отзывчивым и позволяют создать плавный пользовательский опыт даже при масштабных асинхронных операциях.