В современных веб-приложениях часто возникает необходимость ограничивать доступ к определённым страницам или разделам в зависимости от состояния пользователя, его роли или других условий. React Router предоставляет удобные механизмы для реализации таких ограничений.
Защищённый маршрут — это компонент, который проверяет условие доступа перед рендерингом целевого компонента. Если условие не выполнено, пользователь может быть перенаправлен на другую страницу (например, страницу авторизации или страницу ошибки 403).
Пример реализации защищённого маршрута:
import { Navigate, Outlet } from "react-router-dom";
const ProtectedRoute = ({ isAuthenticated, redirectPath = "/login" }) => {
if (!isAuthenticated) {
return <Navigate to={redirectPath} replace />;
}
return <Outlet />;
};
export default ProtectedRoute;
Здесь Outlet используется для вложенных маршрутов, а
Navigate позволяет программно перенаправлять пользователя.
isAuthenticated — логическое значение, определяющее,
авторизован пользователь или нет.
Использование в маршрутах:
import { Routes, Route } from "react-router-dom";
import Dashboard from "./Dashboard";
import Login from "./Login";
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<ProtectedRoute isAuthenticated={userLoggedIn} />}>
<Route path="/dashboard" element={<Dashboard />} />
</Route>
</Routes>
В данном примере доступ к /dashboard будет только у
авторизованных пользователей.
Для более гибкого контроля можно проверять не только факт аутентификации, но и роль пользователя:
const RoleProtectedRoute = ({ userRole, allowedRoles, redirectPath = "/" }) => {
if (!allowedRoles.includes(userRole)) {
return <Navigate to={redirectPath} replace />;
}
return <Outlet />;
};
Применение:
<Route element={<RoleProtectedRoute userRole={currentUser.role} allowedRoles={['admin', 'moderator']} />}>
<Route path="/admin" element={<AdminPanel />} />
</Route>
Таким образом, только пользователи с ролью admin или
moderator смогут попасть на страницу администрирования.
React Router позволяет выполнять условное перенаправление прямо в элементах маршрута:
<Route
path="/profile"
element={userLoggedIn ? <Profile /> : <Navigate to="/login" replace />}
/>
Это удобный способ ограничить доступ к отдельным маршрутам без создания отдельного компонента ProtectedRoute.
Иногда важно не только ограничить маршрут, но и сам доступ к данным внутри компонента. Например, загрузка данных с сервера может зависеть от прав пользователя:
import { useEffect, useState } from "react";
const Dashboard = ({ userRole }) => {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const response = await fetch("/api/data");
const result = await response.json();
// фильтруем данные по роли
if (userRole === "admin") {
setData(result);
} else {
setData(result.filter(item => item.public));
}
};
fetchData();
}, [userRole]);
return <div>{data ? <DataList data={data} /> : "Загрузка..."}</div>;
};
Здесь важное правило: проверка прав должна выполняться как на клиенте, так и на сервере. На клиенте она служит для удобства UX, на сервере — для реальной защиты данных.
React Router поддерживает вложенные маршруты, что позволяет строить иерархию прав доступа:
<Route element={<ProtectedRoute isAuthenticated={userLoggedIn} />}>
<Route path="/app" element={<AppLayout />}>
<Route path="dashboard" element={<Dashboard />} />
<Route element={<RoleProtectedRoute userRole={currentUser.role} allowedRoles={['admin']} />}>
<Route path="admin" element={<AdminPanel />} />
</Route>
</Route>
</Route>
Такой подход обеспечивает:
/app/*,/app/admin.Для защиты данных можно передавать состояние через state
при навигации:
<Navigate to="/login" replace state={{ from: location }} />
На странице логина можно прочитать исходное место назначения:
import { useLocation, useNavigate } from "react-router-dom";
const Login = () => {
const location = useLocation();
const navigate = useNavigate();
const from = location.state?.from?.pathname || "/";
const handleLogin = () => {
authenticateUser();
navigate(from, { replace: true });
};
};
Это позволяет после успешной авторизации возвращать пользователя на страницу, которую он пытался открыть.
state при навигации помогает корректно
возвращать пользователя после авторизации.Эти подходы обеспечивают гибкое управление доступом к страницам и данным, позволяя строить безопасные и масштабируемые приложения на React Router.