0

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;
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
Ali Jand
  • 111
  • 1
  • 3
  • 11

1 Answers1

1

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>
);
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • that's a great answer but the problem is the children elements are working as routes but the content is not rendered this is my private route if (!user) { return (
    404
    ); } return children; }
    – Ali Jand Sep 18 '22 at 17:46
  • 1
    @AliJand You will probably want to re-implement your private route component. Can you clarify what you mean by "content is not rendered"? Can you create a *running* [codesandbox](https://codesandbox.io/) demo of your code that we could inspect live? – Drew Reese Sep 18 '22 at 17:48
  • https://github.com/ichala/short-let-frontend you can check the repo and the branch called 'Update-Routes-Approche' I just updated it right now , what I meant is everything is working great like you said , the only issue is for example the children { path: "/profile", element: , } the route profile works perfectly but the element is not rendered i get empty page – Ali Jand Sep 18 '22 at 17:53
  • 1
    @AliJand Ah, I see. The `PrivateRoutes` needs to render an `Outlet` component (*for the nested routes to render their content into*) instead of the `children` prop. – Drew Reese Sep 18 '22 at 17:56
  • ahaa , can you provide a link to a example or documentation ? – Ali Jand Sep 18 '22 at 17:57
  • okay I got it it should return ; instead of children – Ali Jand Sep 18 '22 at 18:00
  • 1
    @AliJand I did provide a link to an answer of mine that does explain this and provide an example.... but I messed up the link. I've fixed this in my answer. Sorry for any confusion that may've caused. Here it is again: https://stackoverflow.com/a/66289280/8690857 – Drew Reese Sep 18 '22 at 18:00