В React Router управление доступом к маршрутам осуществляется через
редиректы, которые перенаправляют пользователя на
страницы входа или регистрации, если он не прошёл аутентификацию. Для
этого используются компоненты и функции
защиты маршрутов, известные как Protected Routes.
Для контроля доступа создаётся компонент-обёртка, который проверяет
состояние авторизации. Например, состояние авторизации может храниться в
контексте (AuthContext) или глобальном состоянии
(Redux):
import { Navigate } from "react-router-dom";
function ProtectedRoute({ isAuthenticated, children }) {
if (!isAuthenticated) {
return ;
}
return children;
}
isAuthenticated — булевый флаг, указывающий,
авторизован пользователь или нет.children — элементы, доступные только для
авторизованных пользователей.replace — предотвращает добавление лишней записи в
историю браузера при редиректе.В маршрутах приложения защищённые страницы оборачиваются в компонент
ProtectedRoute:
import { Routes, Route } from "react-router-dom";
function App({ isAuthenticated }) {
return (
} />
}
/>
);
}
Таким образом, при попытке перехода на /dashboard без
авторизации пользователь автоматически попадёт на
/login.
Часто требуется возвращать пользователя на страницу, на которую он
пытался попасть до редиректа. Для этого используется объект
state:
import { Navigate, useLocation } from "react-router-dom";
function ProtectedRoute({ isAuthenticated, children }) {
const location = useLocation();
if (!isAuthenticated) {
return ;
}
return children;
}
В компоненте входа можно считать исходный путь:
import { useLocation, useNavigate } from "react-router-dom";
function LoginPage() {
const navigate = useNavigate();
const location = useLocation();
const from = location.state?.from?.pathname || "/";
const handleLogin = () => {
// логика аутентификации
navigate(from, { replace: true });
};
return ;
}
location.state?.from?.pathname — путь, с которого
произошёл редирект.navigate(from, { replace: true }) — после успешного
входа пользователь возвращается на исходную страницу.Если требуется различать доступ по ролям, ProtectedRoute
расширяется проверкой:
function ProtectedRoute({ isAuthenticated, userRole, requiredRole, children }) {
if (!isAuthenticated) {
return ;
}
if (requiredRole && userRole !== requiredRole) {
return ;
}
return children;
}
userRole — роль текущего пользователя.requiredRole — роль, необходимая для доступа.unauthorized — страница, которая отображается при
отсутствии прав.React Router поддерживает ленивую загрузку компонентов. Это позволяет оптимизировать производительность приложения:
import { lazy, Suspense } from "react";
const Dashboard = lazy(() => import("./Dashboard"));
Загрузка... Suspense отображает fallback-контент до завершения
загрузки компонента.Для крупных проектов рекомендуется использовать структуру маршрутов через массив конфигураций:
const routes = [
{ path: "/login", element: },
{
path: "/dashboard",
element: ,
protected: true
},
{
path: "/admin",
element: ,
protected: true,
role: "admin"
}
];
Рендер маршрутов через map с применением
ProtectedRoute:
{routes.map(({ path, element, protected: isProtected, role }, index) => (
{element}
) : (
element
)
}
/>
))}
replace vs push
replace={true} заменяет текущую запись в истории
браузера.replace редирект добавляет новый шаг в историю, что
может вызывать нежелательный эффект «назад» после авторизации.Использование с динамическими параметрами При
редиректе на страницу с параметрами можно передавать их через
state или напрямую в to:
Можно создать хук useAuthGuard для повторного
использования логики:
import { useLocation, Navigate } from "react-router-dom";
import { useAuth } from "./AuthContext";
export function useAuthGuard(children) {
const { isAuthenticated } = useAuth();
const location = useLocation();
if (!isAuthenticated) {
return ;
}
return children;
}
Это позволяет делать компонент максимально компактным:
)} />