React Router предоставляет гибкий инструмент для управления навигацией в приложениях на React. Одной из ключевых задач является организация ролевого доступа к различным маршрутам. Это позволяет ограничивать доступ к страницам в зависимости от роли пользователя (например, администратор, модератор, обычный пользователь).
Для реализации ролевого доступа необходимо создать компонент-обёртку (ProtectedRoute), который проверяет роль пользователя перед отображением целевого компонента. Пример базового подхода:
import { Navigate } from 'react-router-dom';
function ProtectedRoute({ userRole, allowedRoles, children }) {
if (!allowedRoles.includes(userRole)) {
return <Navigate to="/unauthorized" replace />;
}
return children;
}
Ключевые моменты:
userRole — текущая роль пользователя, обычно берётся из
состояния приложения или контекста авторизации.allowedRoles — массив ролей, которым разрешён доступ к
маршруту.Navigate используется для перенаправления на страницу
ошибки или авторизации при несоответствии роли.Для использования ProtectedRoute маршруты объявляются следующим образом:
import { Routes, Route } from 'react-router-dom';
<Routes>
<Route path="/admin" element={
<ProtectedRoute userRole={currentUser.role} allowedRoles={['admin']}>
<AdminPanel />
</ProtectedRoute>
} />
<Route path="/profile" element={
<ProtectedRoute userRole={currentUser.role} allowedRoles={['user', 'admin']}>
<UserProfile />
</ProtectedRoute>
} />
<Route path="/unauthorized" element={<UnauthorizedPage />} />
</Routes>
Особенности:
Routes и Route остаётся
стандартной, что облегчает поддержку.element передаётся непосредственно JSX-компонент,
обёрнутый проверкой роли.Для упрощения передачи информации о пользователе и его роли удобно использовать React Context:
import { createContext, useContext } from 'react';
const AuthContext = createContext(null);
export function AuthProvider({ children, user }) {
return <AuthContext.Provider value={user}>{children}</AuthContext.Provider>;
}
export function useAuth() {
return useContext(AuthContext);
}
Далее ProtectedRoute может быть переписан так, чтобы не требовать
явного userRole:
function ProtectedRoute({ allowedRoles, children }) {
const user = useAuth();
if (!user || !allowedRoles.includes(user.role)) {
return <Navigate to="/unauthorized" replace />;
}
return children;
}
В некоторых случаях требуется, чтобы доступ зависел от параметров маршрута, например, ID пользователя:
<Route path="/profile/:id" element={
<ProtectedRoute allowedRoles={['admin', 'user']}>
<UserProfile />
</ProtectedRoute>
} />
Внутри компонента UserProfile можно дополнительно
проверять соответствие текущего пользователя параметру
id:
import { useParams } from 'react-router-dom';
import { useAuth } from './AuthContext';
function UserProfile() {
const { id } = useParams();
const user = useAuth();
if (user.role !== 'admin' && user.id !== id) {
return <UnauthorizedPage />;
}
return <div>Профиль пользователя {id}</div>;
}
Для более сложных приложений часто создаётся система ролей и прав, где каждая роль имеет набор разрешений. Это позволяет:
Пример проверки разрешений:
function ProtectedRoute({ requiredPermission, children }) {
const user = useAuth();
if (!user || !user.permissions.includes(requiredPermission)) {
return <Navigate to="/unauthorized" replace />;
}
return children;
}
/unauthorized),
чтобы не было “мертвых зон”.Эта структура обеспечивает гибкое и безопасное управление доступом, полностью интегрированное с React Router, и подходит как для небольших приложений, так и для крупных корпоративных проектов с многоуровневой системой ролей.