Back to all posts

Building A Multi-pages SPA with React Router


What is routing?

In a single page react application routing refers to the process of navigating between different pages without triggering a full page reload.

In this blog we will build small project to understand this with example.

npm install react-router-dom

At first we will install this package. Check more about this in site: https://reactrouter.com/en/main

Then we will work with this package

//App.jsx
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import HomePage from "./pages/Home";

const router = createBrowserRouter([ 
  {
    path: "/",
    element: <HomePage />,
  },
]);

function App() {
  return <RouterProvider router={router} />;
}

export default App;

Alternative way of defining routes

//app.jsx
import {
  createBrowserRouter,
  RouterProvider,
  Route,
  createRoutesFromElements,
} from "react-router-dom";
import HomePage from "./pages/Home";
import ProductsPage from "./pages/Products";

const routerDefinition = createRoutesFromElements(
  <Route path="/" element={<HomePage />}>
    <Route path="/Products" element={<ProductsPage />} />
  </Route>,
);

const router = createBrowserRouter(routerDefinition);

// const router = createBrowserRouter([
//   {
//     path: "/",
//     element: <HomePage />,
//   },
//   {
//     path: "/Products",
//     element: <ProductsPage />,
//   },
// ]);

function App() {
  return <RouterProvider router={router} />;
}

export default App;

Layout and Nested Routes

To create above layout we need to change out current app.js code.

So we create a new file name Root.jsx inside pages folder

//Root.jsx
import { Outlet } from "react-router-dom";
import MainNavigation from "../components/MainNavigation";
import classes from "./Root.module.css";
function RootLayout() {
  return (
    <>
      <MainNavigation />
      <main className={classes.content}>
        <Outlet />
      </main>
    </>
  );
}

export default RootLayout;

So now we need to change our app.js code like below

//app.jsx
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import HomePage from "./pages/Home";
import ProductsPage from "./pages/Products";
import RootLayout from "./pages/Root";

const router = createBrowserRouter([
  {
    path: "/",
    element: <RootLayout />,
    children: [
      {
        path: "/",
        element: <HomePage />,
      },
      { path: "/Products", element: <ProductsPage /> },
    ],
  },
]);

function App() {
  return <RouterProvider router={router} />;
}

export default App;

404 page in routing

Inside App.jsx page

//App.jsx
import ErrorPage404 from "./pages/Error";

const router = createBrowserRouter([
  {
    path: "/",
    element: <RootLayout />,
    errorElement: <ErrorPage404 />,
    children: [
      {
        path: "/",
        element: <HomePage />,
      },
      { path: "/Products", element: <ProductsPage /> },
    ],
  },
]);

inside error.jsx file

//error.jsx
import MainNavigation from "../components/MainNavigation";
function ErrorPage404() {
  return (
    <>
      <MainNavigation />
      <main className="content">
        <h1>An error occurred!</h1>
        <p>Could not find page!</p>
      </main>
    </>
  );
}

export default ErrorPage404;

NavLinks

Working with navigation element we need make nav element active based on route. For example
We can build this using NavLink

In MainNavigation.jsx

<nav>
        <ul className={classes.list}>
          <li>
            <NavLink
              to="/"
              className={({ isActive }) =>
                isActive ? classes.active : undefined
              }
            >
              Home
            </NavLink>
          </li>
          <li>
            <NavLink
              to="/Products"
              className={({ isActive }) =>
                isActive ? classes.active : undefined
              }
              end
            >
              Products
            </NavLink>
          </li>
        </ul>
      </nav>

Navigation Programatically

//home.jsx
import { Link, useNavigate } from "react-router-dom";

function HomePage() {
  const navigate = useNavigate();
  function naviagtionHandler() {
    navigate("/products");
  }

  return (
    <>
      <h1>Home Page</h1>
      <p>
        Go tp <Link to="/Products">Product Page</Link>
      </p>
      <p>
        <button onClick={naviagtionHandler}>Navigation</button>
      </p>
    </>
  );
}

export default HomePage;

Dynamic Routes

If your are building e-commerce project then you have a product list page there you need to have dynamic routes like this.

Then we need to configure this dynamically.

//App.jsx
const router = createBrowserRouter([
  {
    path: "/",
    element: <RootLayout />,
    errorElement: <ErrorPage404 />,
    children: [
      {
        path: "/",
        element: <HomePage />,
      },
      { path: "/products", element: <ProductsPage /> },
      { path: "/products/:productID", element: <ProductDetailsPage /> },
    ],
  },
]);

Then create new jsx file inside pages folder with name ProductDetailsPage

import { useParams } from "react-router-dom";
function ProductDetailsPage() {
  const prdId = useParams();
  return (
    <>
      <h1>Product Details Page</h1>
      <p>Product Id: {prdId.productID}</p>
    </>
  );
}
export default ProductDetailsPage;