React Router

Using The Odin Project as a guide

What Problem Does Routing Solve?

  • Single Page Applications (SPAs) do not reload pages.
  • Users still expect URLs to map to "pages."
  • Routing enables:
    • Different screens for different URLs
    • Back/forward navigation i.e. History API
    • URL-based state

React Router has 3 types

As if things werren't complicated enough!
https://reactrouter.com/start/modes#declarative

  • Framework
  • Data (odin uses this)
  • Declarative (❤️ simplest, but least powerful)

Keep an eye on the top selector!

Another Gotcha - LLMs ARE Out of date!

Installing React Router

npm i react-router

https://reactrouter.com/start/declarative/installation

Creating Your First Router WRONG...

Another Gotcha - LLMs ARE Out of date!
You will get this!!!

import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Home from "./Home";
import About from "./About";

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

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

Creating Your First Router RIGHT...

https://reactrouter.com/start/modes#data

import {createBrowserRouter, RouterProvider,} from "react-router";

let router = createBrowserRouter([
  {
    path: "/",
    Component: Root,
    loader: loadRootData,
  },
]);

ReactDOM.createRoot(root).render(
  <RouterProvider router={router} />,
);

Adding Another path! (Odin project example)

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router";
import App from "./App";
import Profile from "./Profile";

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

createRoot(document.getElementById("root")).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>
);

Understanding path and element

  • path → URL in the browser
  • element → component to render
  • Visiting /about renders <About />

Navigating with <Link>

  • Browser reloads when clicking navbar links
  • This defeats the purpose of React Router
  • Use <Link> component instead of <a> tag
  • <Link> prevents full page reloads
  • Enables client-side navigation
import { Link } from "react-router";
<Link to="/about">About Page</Link>

Programmatic Navigation with useNavigate

import { useNavigate } from "react-router";

const navigate = useNavigate();

function handleClick() {
  navigate("/");
}

Another example

https://api.reactrouter.com/v7/functions/react_router.useNavigate.html

import { useNavigate } from "react-router";

function SomeComponent() {
  let navigate = useNavigate();
  return (
    <button
      onClick={() => {
        navigate(-1);
      }}
    />
  );
}

Route Parameters

{
  path: "/users/:id",
  element: <UserPage />
}

Access them:

import { useParams } from "react-router";
const { id } = useParams();

Nested Routes (Example)

When you have layouts or sections with sub-pages.

Amazing docs here

Nested Routes Diagram

const router = createBrowserRouter([
  {
    path: "/",
    element: (
      <>
        <h1>React Router</h1>
        <nav>
          <Link to="/">Home</Link>
          <Link to="/user/profile">User</Link>
        </nav>
        <Outlet />
      </>
    ),
    children: [
      { index: true, element: <Home /> },

      {
        path: "user",
        element: <UserLayout />,
        children: [
          { path: "profile", element: <ProfilePage /> }, // /user/profile
          { path: "account", element: <AccountPage /> }, // /user/account
        ],
      },

      { path: "*", element: <NoMatch /> },
    ],
  },
]);

The Outlet Component

  • <Outlet> renders child routes
  • Place it in parent route component where children should appear

https://stackoverflow.com/a/76246822

Rendering Child Routes with <Outlet>

// router.tsx / router.js
import {
  createBrowserRouter,
  RouterProvider,
  Outlet,
  Link,
  NavLink,
} from "react-router";

import Home from "./Home";
import NoMatch from "./NoMatch";

// ----- Nested pages -----
const ProfilePage = () => <h2>Nested Profile Page</h2>;
const AccountPage = () => <h2>Nested Account Page</h2>;

// ----- Layout for /user/* -----
const UserLayout = () => {
  return (
    <div>
      <h1>User: Robin Wieruch</h1>

      <nav>
        {/* relative links; become /user/profile and /user/account */}
        <NavLink to="profile">Profile</NavLink>
        <NavLink to="account">Account</NavLink>
      </nav>

      {/* where nested routes render */}
      <Outlet />
    </div>
  );
};

Routing Hooks Cheat Sheet

Task Hook
Navigate via code useNavigate()
Read URL params useParams()
Read query params useSearchParams()
Current URL info useLocation()
Render child routes <Outlet />

Handling 404 Pages

{
  path: "*",
  element: <h1>404 - Not Found</h1>
}

Example Application Structure

  • Home page
  • Shop page
  • Product detail page /shop/:id
  • Add-to-cart → redirect using useNavigate
  • 404 page

Summary

React Router provides:

  • Client-side navigation
  • URL-based state
  • Nested layouts
  • Programmatic redirects
  • Dynamic routes

Explore the official docs for more!