Skip to content

React Router Setup with Dynamic Routes, Layouts, and Protected Pages

App.tsx

tsx
import {BrowserRouter, Route, Routes} from "react-router-dom";
import ProtectedRoute from "./auth/ProtectedRoute";
import Layout from "./layouts/Layout";
import Dashboard from "./pages/app/dashboard/Dashboard";
import Home from "./pages/app/home/Home";
import Login from "./pages/auth/login/Login";

function App() {
  const routes = [
    {
      path: "/",
      layout: Layout,
      children: [{path: "", component: <Home />, protected: false}],
    },
    {
      path: "/login",
      component: <Login />,
      protected: false,
    },
    {
      path: "/dashboard",
      component: <Dashboard />,
      protected: true,
    },
  ];

  return (
    <BrowserRouter>
      <Routes>
        {routes.map((item, index) => {
          // If there's a layout, nest children under it
          if (item.layout) {
            const Layout = item.layout;
            return (
              <Route key={index} path={item.path} element={<Layout />}>
                {item.children.map((child, j) => {
                  const element = child.protected ? (
                    <ProtectedRoute>{child.component}</ProtectedRoute>
                  ) : (
                    child.component
                  );

                  return (
                    <Route
                      key={j}
                      index={child.path === ""}
                      path={child.path !== "" ? child.path : undefined}
                      element={element}
                    />
                  );
                })}
              </Route>
            );
          }

          // No layout route
          const element = item.protected ? (
            <ProtectedRoute>{item.component}</ProtectedRoute>
          ) : (
            item.component
          );

          return <Route key={index} path={item.path} element={element} />;
        })}
      </Routes>
    </BrowserRouter>
  );
}

export default App;

ProtectedRouter.tsx

tsx
import type {ReactNode} from "react";
import {Navigate} from "react-router-dom";

const isAuthenticated = () => {
  // Replace with your actual auth logic
  return localStorage.getItem("token") !== null;
};

const ProtectedRoute: React.FC<{children: ReactNode}> = ({children}) => {
  return isAuthenticated() ? children : <Navigate to="/login" replace />;
};

export default ProtectedRoute;