react router dom and role based

82 Views Asked by At

I'm struggling to implement dynamic role-based routing with the latest version of react-router-dom (v6.22.3). I have some ideas, but I'm finding it difficult to implement them fully.

Notes:

  1. I familiar with examples described here [link][1]
  2. Goal description :
    1. define roles in the router
    2. consume it in the outlet
  3. The entire path are protected except login. so we dont need to add protected route (the app is function as protected) , just need to handle the role base

Here's what I've tried:

I've set up a mapping for my pages and defined roles for each page:

export const paths = {
  boo: { path: "/boo", roles: [] },
  foo: { path: "/foo", roles: ["admin", "manager"] },
};

And here's how I've set up my router: (defining the roles inside the id prop is the best option i found)

const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    children: [
      { path: paths.details.boo, element: <Boo/>, id: createRouteId("boo") },
      { path: paths.details.foo, element: <Foo/>, id: createRouteId("Foo") },
    ],
    errorElement: <ErrorPage />,
  },
  {
    path: "/login",
    element: <Login />,
  },
]);

export default router;

Now, I'm wondering if there's any way to use a property other than "id" to uniquely identify routes. However, let's assume "id" is the best option.

In my App.tsx, I'm using a custom hook to get the user object, which looks like this:

{userName:string,roles:roles[],...}

I'm also attempting to check if the user has valid roles for the current route:

const isValidRole = (userRoles: string[], outletRole: string[]) => {
  return userRoles.some((role) => outletRole.includes(role));
};

Here's my App.tsx component: (here we use outlet and i try to consume the roles based on the location with the outlet)

function App() {
  const { user } = useAuth();
  const getRouteIdFromOutlet = useOutlet();
  const [isValidRole] = useState(isRoleValid(user.roles, JSON.parse(getRouteIdFromOutlet.props.id)));

  if (!user) return <Login />;
  if(!isValidRole) throw new Error("Unauthorized"); // the error page will know what to render

  return (
    <Layout>
      <NavbarDesktop />
      <Content style={{ padding: "0 48px" }}>
        <Outlet />
      </Content>
    </Layout>
  );
}

now the const getRouteIdFromOutlet = useOutlet(); is the closest option i found in order to read the id from the route and utilize it here

0

There are 0 best solutions below