Обработка ошибок при ленивой загрузке

В TanStack Router ленивое (асинхронное) подключение компонентов и данных позволяет оптимизировать производительность приложения, загружая только необходимый код и данные по мере надобности. Однако при использовании ленивой загрузки необходимо учитывать возможность ошибок, связанных с динамическим импортом, сетевыми сбоями или некорректными данными. TanStack Router предоставляет гибкие механизмы для перехвата и обработки таких ошибок.


Ленивые маршруты и асинхронные компоненты

Ленивая загрузка компонентов в TanStack Router реализуется через функцию lazy, которая принимает функцию динамического импорта:

import { lazy } from '@tanstack/router';

const HomePage = lazy(() => import('./pages/HomePage'));
const ProfilePage = lazy(() => import('./pages/ProfilePage'));

Внутри маршрутизатора ленивые компоненты указываются как обычные компоненты:

const router = createRouter({
  routes: [
    {
      path: '/',
      component: HomePage,
    },
    {
      path: '/profile',
      component: ProfilePage,
    },
  ],
});

При этом TanStack Router автоматически обрабатывает состояние загрузки компонента, но для обработки ошибок необходима дополнительная конфигурация.


Перехват ошибок через errorElement

Каждый маршрут в TanStack Router может содержать поле errorElement, которое рендерится при возникновении ошибки в маршруте, включая ошибки ленивой загрузки:

import ErrorPage from './pages/ErrorPage';

const router = createRouter({
  routes: [
    {
      path: '/profile',
      component: ProfilePage,
      errorElement: <ErrorPage />,
    },
  ],
});

В этом случае, если динамический импорт не удастся (например, файл отсутствует или произошел сбой сети), TanStack Router отобразит ErrorPage, передав объект ошибки в компонент.


Использование useRouteError для получения ошибки

Компонент, указанный в errorElement, может получить информацию об ошибке с помощью хука useRouteError:

import { useRouteError } from '@tanstack/router';

function ErrorPage() {
  const error = useRouteError();
  
  return (
    <div>
      <h1>Произошла ошибка</h1>
      <p>{error.message}</p>
    </div>
  );
}

useRouteError возвращает объект ошибки, который может быть любым: от стандартного Error до пользовательских объектов. Это позволяет выводить подробную информацию о проблеме и реализовывать кастомные стратегии обработки.


Ленивые загрузки с Suspense

TanStack Router тесно интегрирован с React Suspense, что позволяет обрабатывать состояние загрузки ленивых компонентов:

import { Suspense } from 'react';

const router = createRouter({
  routes: [
    {
      path: '/profile',
      component: (
        <Suspense fallback={<div>Загрузка...</div>}>
          <ProfilePage />
        </Suspense>
      ),
      errorElement: <ErrorPage />,
    },
  ],
});

Поле fallback отображается до завершения загрузки асинхронного компонента. Если же загрузка завершится ошибкой, будет показан errorElement.


Асинхронные загрузчики данных

Помимо компонентов, TanStack Router поддерживает ленивую загрузку данных через loader:

const profileLoader = async () => {
  const response = await fetch('/api/profile');
  if (!response.ok) throw new Error('Не удалось загрузить профиль');
  return response.json();
};

const router = createRouter({
  routes: [
    {
      path: '/profile',
      component: ProfilePage,
      loader: profileLoader,
      errorElement: <ErrorPage />,
    },
  ],
});

Если loader выбрасывает ошибку, маршрутизатор автоматически передаст её в errorElement. В ErrorPage можно вывести текст ошибки, статус HTTP или предложить пользователю повторить загрузку.


Обработка ошибок на уровне всего приложения

TanStack Router поддерживает глобальную обработку ошибок через корневой маршрут. Например:

const rootRoute = {
  path: '/',
  component: <RootLayout />,
  errorElement: <GlobalErrorPage />,
  children: [
    { path: '/', component: HomePage },
    { path: '/profile', component: ProfilePage, loader: profileLoader },
  ],
};

const router = createRouter({ routes: [rootRoute] });

Любая ошибка в дочерних маршрутах будет перехвачена глобальным errorElement, если локальные errorElement не определены. Это упрощает централизованное логирование ошибок и создание единообразного интерфейса уведомления пользователя.


Практические рекомендации

  • Всегда задавать errorElement для ленивых маршрутов и асинхронных загрузчиков данных.
  • Использовать useRouteError для получения подробной информации об ошибке.
  • Комбинировать Suspense и errorElement, чтобы разделить состояние загрузки и ошибки.
  • Для критичных данных использовать глобальный обработчик ошибок для предотвращения падения всего приложения.
  • Обрабатывать специфические ошибки, например сетевые сбои или ошибки парсинга, чтобы отображать пользователю понятные сообщения.

TanStack Router предоставляет полный инструментарий для безопасной и предсказуемой ленивой загрузки, позволяя управлять ошибками как на уровне отдельных маршрутов, так и на уровне всего приложения. Такой подход улучшает стабильность и UX, особенно в крупных приложениях с динамическими компонентами и асинхронными данными.