Home > OS >  What's the best approach to map routes in react with user privilege?
What's the best approach to map routes in react with user privilege?

Time:09-19

Question :

the complexity inside the .map function is so high, any suggestions about reorganizing the code to map the routes and apply protection to them at the same time? i tried adding the routes inside an array so I can loop through them, my code is working perfectly but I'm searching for a better approach since this look so complex and wrong

This is my Routes config file

import Login from '../Pages/Auth/Login';
import Register from '../Pages/Auth/Register';
import Home from '../Pages/Home/Home';

const routes = [
  {
    path: '/',
    component: <Home />,
    protected: false,
  },
  {
    path: '/login',
    component: <Login />,
    protected: false,
  },
  {
    path: '/register',
    component: <Register />,
    protected: false,
  },

];

export default routes;

this is my App.js file

import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { isLoggedIn } from './redux/slices/auth';
import './App.css';
import Layout from './Layouts/Layout';
import routes from './config/routes';

function App() {
  const dispatch = useDispatch();
  const user = useSelector((state) => state.user);
  useEffect(() => {
    dispatch(isLoggedIn());
  }, []);
  return (
    <>
      <BrowserRouter>
        <Layout>
          <Routes>
            {routes.map((route, i) => (
              <>
                {route.path === '/' ? (<Route key={i} exact path={route.path} element={route.component} />) : ((user && route.protected && <Route key={i} path={route.path} element={route.component} />) || (!user && !route.protected && <Route key={i} path={route.path} element={route.component} />))}
              </>
            ))}

          </Routes>
        </Layout>
      </BrowserRouter>
    </>
  );
}

export default App;

CodePudding user response:

react-router-dom is already very good and the rendering of the routes, and this isn't something you need to reinvent the wheel for. I'd suggest creating a PrivateRoutes layout route component (see this post for implementation details) and reconfigure your routes declaration so it can be directly passed to the useRoutes hook that returns an object to be directly rendered.

Example:

import Login from '../Pages/Auth/Login';
import Register from '../Pages/Auth/Register';
import Home from '../Pages/Home/Home';
...
import PrivateRoutes from '../components/PrivateRoutes';

const routesConfig = [
  {
    path: '/',
    element: <Home />,
  },
  {
    path: '/login',
    element: <Login />,
  },
  {
    path: '/register',
    element: <Register />,
  },
  {
    element: <PrivateRoutes />, // <-- checks auth status
    children: [
      {
        path: "/dashboard",
        element: <Dashboard />,
      },
      {
        path: "/profile",
        element: <Profile />,
      },
      ... other protected routes ...
    ],
  },
  ... other unprotected routes ...
];

export default routesConfig;

...

import { useRoutes } from 'react-router-dom';
import { isLoggedIn } from './redux/slices/auth';
import './App.css';
import Layout from './Layouts/Layout';
import routesConfig from './config/routes';

function App() {
  const routes = useRoutes(routesConfig);

  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(isLoggedIn());
  }, []);

  return (
    <Layout>
      {routes}
    </Layout>
  );
}

Wrap App with the BrowserRouter so the useRoutes hook can be used in App.

import { BrowserRouter } from 'react-router-dom';

...

return (
  <BrowserRouter>
    <App />
  </BrowserRouter>
);
  • Related