Проверка аутентификации в loader

В современном веб-приложении часто требуется контролировать доступ к определённым маршрутам на основе состояния аутентификации пользователя. В React Router v6+ появился механизм loader, который позволяет загружать данные до рендера компонента маршрута. Это удобное место для проверки авторизации, так как можно предотвратить рендеринг защищённых страниц, если пользователь не авторизован.

Основные концепции

  • loader — асинхронная функция, связанная с маршрутом, которая выполняется перед рендерингом компонента.
  • Проверка аутентификации в loader позволяет прервать переход и перенаправить пользователя на страницу входа без рендера защищённого компонента.
  • redirect из react-router-dom используется для выполнения перенаправления внутри loader.

Пример базовой проверки

import { redirect } from "react-router-dom";

export async function authLoader({ request }) {
  const token = localStorage.getItem("authToken");

  if (!token) {
    return redirect("/login");
  }

  return null; // Разрешаем рендеринг компонента
}
  • В этом примере authLoader проверяет наличие токена в localStorage.
  • Если токен отсутствует, вызывается redirect("/login"), который немедленно перенаправляет пользователя.
  • Если токен есть, функция возвращает null, и маршрут продолжает рендериться.

Использование с маршрутом

import { createBrowserRouter } from "react-router-dom";
import Dashboard from "./pages/Dashboard";
import Login from "./pages/Login";
import { authLoader } from "./loaders/authLoader";

const router = createBrowserRouter([
  {
    path: "/dashboard",
    element: <Dashboard />,
    loader: authLoader,
  },
  {
    path: "/login",
    element: <Login />,
  },
]);

export default router;
  • В данном примере компонент Dashboard защищён через loader.
  • Любой пользователь, не имеющий токена, будет перенаправлен на /login.

Асинхронная проверка через API

В реальных приложениях часто требуется проверять токен на сервере.

import { redirect } from "react-router-dom";

export async function authLoader({ request }) {
  const token = localStorage.getItem("authToken");

  if (!token) {
    return redirect("/login");
  }

  const response = await fetch("/api/validate-token", {
    headers: { Authorization: `Bearer ${token}` },
  });

  if (!response.ok) {
    localStorage.removeItem("authToken");
    return redirect("/login");
  }

  return null;
}
  • Здесь loader выполняет HTTP-запрос к API для проверки токена.
  • При недействительном токене происходит удаление из localStorage и перенаправление.
  • Асинхронная логика полностью поддерживается в loader, что обеспечивает безопасный доступ к защищённым маршрутам.

Передача данных через loader

loader может возвращать данные, которые затем доступны через useLoaderData:

import { useLoaderData } from "react-router-dom";

export async function dashboardLoader({ request }) {
  const token = localStorage.getItem("authToken");

  if (!token) return redirect("/login");

  const response = await fetch("/api/user-data", {
    headers: { Authorization: `Bearer ${token}` },
  });

  const data = await response.json();
  return data;
}

// В компоненте
function Dashboard() {
  const userData = useLoaderData();
  return (
    <div>
      <h1>Добро пожаловать, {userData.name}</h1>
    </div>
  );
}
  • loader выполняет проверку аутентификации и одновременно загружает данные пользователя.
  • Это упрощает архитектуру: компонент получает только уже проверенные и подготовленные данные.

Обработка ошибок и редиректов

Для комплексных сценариев можно использовать errorElement:

const router = createBrowserRouter([
  {
    path: "/dashboard",
    element: <Dashboard />,
    loader: authLoader,
    errorElement: <div>Ошибка загрузки страницы</div>,
  },
]);
  • Ошибки в loader автоматически передаются в errorElement.
  • Перенаправления с redirect также корректно обрабатываются, предотвращая рендер защищённого компонента.

Вывод

Проверка аутентификации в loader React Router позволяет:

  • Контролировать доступ на уровне маршрута до рендера компонента.
  • Асинхронно валидировать токены через API.
  • Передавать безопасные данные в компонент через useLoaderData.
  • Обрабатывать ошибки и редиректы централизованно, не создавая сложных проверок внутри компонентов.

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