'Role based react-router
What is the best way to conditionally render routes in react-router based on user role. I have a case where not all roles have permission to view certain routes. And also I need to deal with subroutes. So if one of main routes is something like /posts I want only admin and student to access that route and its subroutes (posts/today for example). I am using react-router version 5.3.2.
Solution 1:[1]
I has a similar issue with react-router-dom v6, but you can tweak it to your benefits
First create a source of truth wheither a user can or can't access some route, for roles based auth I'd think of a hook like
export function useUserRoles() {
// some logic or api call to get the roles
// for demonstration purposes it's just hard coded
const userRoles: Array<typeof UserRoles[number]> = ['admin', 'root'];
// return the current user roles
return userRoles;
}
Then we make a component that can decide using that hook weither to render the route or redirect to login(or some page)
export function RolesAuthRoute({ children, roles }: { children: ReactNode, roles: Array<typeof UserRoles[number]> }) {
const userRoles = useUserRoles();
const canAccess = userRoles.some(userRole => roles.includes(userRole));
if (canAccess)
return (
<Fragment>
{children}
</Fragment>
);
return (<Navigate to="/dashboard/login" />);
}
then the route defined wraps that component to act as a guard that decide if you can or can't access that route
<Route
path="users"
element={
<Suspense fallback={<ProjectLayoutLoader />}>
<RolesAuthRoute roles={['admin']}>
<ProjectUsersPage />
</RolesAuthRoute>
</Suspense>
} />
Solution 2:[2]
i have two role "parent" and "manager" and i write this code and work it for me:
function App(props) {
return (
<div className="App ">
<Routes>
<Route exact path="/" element={<Home />} />
<Route exact path="/" element={<ProtectedRoute />}>
<Route exact path="/admin" element={<StudentLists />} />
<Route exact path="/student_pk_api/:id" element={<IdFilter />} />
<Route exact path="/absentes" element={<AbsentStu />} />
<Route exact path="/students_by_field_and_level_:grade_api/:studyfield_code" element={<FieldGradeFilter />} />
<Route exact path="/absent_yesterday_api" element={<YesterdayAbs />} />
<Route exact path="/absent_today_api" element={<TodayAbs />} />
</Route>
<Route exact path="/" element={<ProtectedUserRoute />}>
<Route exact path="/users" element={<SchoolDit />} />
</Route>
</Routes>
</div>
);
}
for cheking roles i write two function:
for manager role:
const ProtectedRoute = () => {
const [manager, setmaneger] = useState(localStorage.getItem("role")==="manager"?true:null);
return manager ? <Outlet /> : <Navigate to="/" />;
}
export default ProtectedRoute
for parent role:
const ProtectedUserRoute = () => {
const [parent, setParent] = useState(localStorage.getItem("role")==="parent"?true:null);
return parent ? <Outlet /> : <Navigate to="/" />;
}
export default ProtectedUserRoute
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Mhd Louay Al-osh |
Solution 2 | maede |