Frontend Master

JavaScript Curriculum

React Router
+60 XP

React Router

medium
~35 min·60 XP

The coffee shop app needs a home page, a menu page, individual item detail pages at /menu/:id, and a cart. Each page is a React component — React Router wires URL paths to the right component.

React Router

React Router is the standard routing library for React. It maps URL paths to components, handles navigation without page reloads, and provides hooks to read URL parameters and navigate programmatically.

Setup, Routes, Link, useParams, useNavigate

The four core concepts — all in one place:

router-setup.jsx

BrowserRouter wraps the app. Routes renders the first matching Route. Each Route maps a path to a component.

// main.jsx — wrap the app
import { BrowserRouter } from 'react-router-dom'

ReactDOM.createRoot(document.getElementById('root')).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
)

// App.jsx — define routes
import { Routes, Route } from 'react-router-dom'

function App() {
  return (
    <Routes>
      <Route path="/"           element={<Home />} />
      <Route path="/menu"       element={<Menu />} />
      <Route path="/menu/:id"   element={<ItemDetail />} />
      <Route path="/cart"       element={<Cart />} />
      <Route path="*"           element={<NotFound />} />
    </Routes>
  )
}
URL simulator
localhost:3000/
Renders: Home component
ℹ️Note
"> Using a regular `<a href="/menu">` causes a full page reload — the entire React app reinitialises. `<Link to="/menu">` updates the URL and re-renders only what changed. Same for programmatic navigation: `useNavigate()` instead of `window.location.href = '/menu'`.

Navigation Patterns — With Browser History

Simulate navigation, history stack, and useNavigate patterns:

navigation.jsx
localhost:3000/
🏠
Home
/
History stack
/
// Programmatic navigation patterns:

// After form submit → go to confirmation:
const navigate = useNavigate()
const handleSubmit = async (data) => {
  const order = await submitOrder(data)
  navigate(`/orders/${order.id}`)
}

// Protected route — redirect if not logged in:
function PrivateRoute({ children }) {
  const { user } = useAuth()
  if (!user) {
    return <Navigate to="/login" replace />
  }
  return children
}

// Go back after action:
const navigate = useNavigate()
<button onClick={() => navigate(-1)}>Back</button>

// Replace entry (login → dashboard, no back to login):
navigate('/dashboard', { replace: true })
💡navigate(-1) vs Link
Use `navigate(-1)` for a programmatic back button — it goes to the previous history entry. Use `navigate('/path', { replace: true })` when you don't want the user to be able to go back (e.g., after login, redirect to dashboard and replace the login entry).

Nested Routes — Layout + Outlet

Share a layout across multiple routes using nesting:

nested-routes.jsx
└─
└─
└─
└─
└─
└─
Current URL
localhost:3000/menu
Outlet chain
Layout → renders
Menu → renders
MenuIndex
⚠️Outlet is required for child routes to render
If a parent route has child routes, it must render `<Outlet />` somewhere in its JSX — that is where the matched child component will appear. Forgetting `<Outlet />` means child routes match in the URL but nothing renders.

Your Challenge

Build a mini coffee shop router: BrowserRouter in main.jsx. Layout route at / with Header, <Outlet />, Footer. Child routes: index→Home, menu→MenuList, menu/:id→ItemDetail, cart→Cart, *→NotFound. In ItemDetail: useParams() to get id, find item, show name and price. NavLink for active styles.

Challenge

Set up BrowserRouter. Define routes: / → Home, /menu → MenuList, /menu/:id → ItemDetail, /cart → Cart, * → NotFound. Add a nav with NavLink. In ItemDetail, read the id param and find the matching item. Add a 'Back to menu' link.

BrowserRouterRoutesRouteLinkNavLinkuseParamsuseNavigateOutletnested-routesindex-routeNavigate
React Router | Nexus Learn