React Router
By default, React builds Single Page Applications (SPAs) — applications where the browser loads only one HTML page and React dynamically updates the content as the user navigates. However, React itself does not include routing — the ability to navigate between different "pages" or views.
React Router is the most widely used library for adding navigation to React applications. It maps URL paths to specific components, making it appear to users as though they are visiting different pages — even though the page never actually reloads.
Installing React Router
npm install react-router-dom
This installs React Router v6 (the current major version). All examples in this topic use v6 syntax.
Core Components of React Router
- BrowserRouter — Wraps the entire application and enables routing using the browser's URL history
- Routes — A container that holds all the Route definitions
- Route — Defines a mapping between a URL path and a component
- Link — Renders a navigation link that updates the URL without reloading the page
- useNavigate — A Hook for programmatic navigation (e.g., redirecting after form submission)
- useParams — A Hook to read dynamic URL parameters
Basic Setup — Multi-Page App
Setting up three pages: Home, About, and Contact:
// src/pages/Home.jsx
function Home() {
return <h2>Welcome to the Home Page</h2>;
}
export default Home;
// src/pages/About.jsx
function About() {
return <h2>About Us</h2>;
}
export default About;
// src/pages/Contact.jsx
function Contact() {
return <h2>Contact Us</h2>;
}
export default Contact;
// src/App.jsx
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link> |
<Link to="/about">About</Link> |
<Link to="/contact">Contact</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</BrowserRouter>
);
}
export default App;
When a user clicks "About", the URL changes to /about and the About component is rendered — without any page reload. The navigation links use <Link> instead of <a> to prevent browser navigation and stay in the React app.
Dynamic Routes with URL Parameters
Dynamic routes use a colon (:) to define a variable segment in the URL. For example, /user/42 and /user/99 both match the path /user/:id:
// src/pages/UserProfile.jsx
import { useParams } from 'react-router-dom';
function UserProfile() {
const { id } = useParams(); // Reads the :id from the URL
return (
<div>
<h2>User Profile</h2>
<p>Showing profile for user ID: {id}</p>
</div>
);
}
export default UserProfile;
// In App.jsx
<Route path="/user/:id" element={<UserProfile />} />
Navigating to /user/42 will render the UserProfile component, and useParams() will return { id: "42" }.
Nested Routes
React Router supports nested routes — routes defined inside other routes. This is useful for layouts where a sidebar or header stays constant while the inner content changes:
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="overview">Overview</Link> |
<Link to="settings">Settings</Link>
</nav>
<Outlet /> {/* Child routes render here */}
</div>
);
}
<Route path="/dashboard" element={<Dashboard />}>
<Route path="overview" element={<Overview />} />
<Route path="settings" element={<Settings />} />
</Route>
The <Outlet /> component from React Router acts as a placeholder where the matched child route's component is rendered.
Programmatic Navigation with useNavigate
Sometimes navigation needs to happen in code — such as redirecting to a dashboard after a successful login:
import { useNavigate } from 'react-router-dom';
function LoginForm() {
const navigate = useNavigate();
function handleLogin() {
// Imagine authentication logic here
navigate("/dashboard"); // Redirect to dashboard
}
return <button onClick={handleLogin}>Log In</button>;
}
useNavigate() returns a function that can be called to change the current route programmatically.
Handling 404 — Not Found Page
A catch-all route with path="*" can render a custom 404 page for any URL that doesn't match a defined route:
function NotFound() {
return <h2>404 — Page Not Found</h2>;
}
// In Routes
<Route path="*" element={<NotFound />} />
Key Points
- React Router adds client-side navigation to React SPAs without page reloads.
BrowserRouterwraps the app,Routesgroups routes, andRoutemaps paths to components.- Use
<Link>instead of<a>to navigate without reloading the page. - Dynamic URL segments are defined with
:paramNameand read withuseParams(). - Use
useNavigate()for programmatic navigation after events like form submission. - Nested routes with
<Outlet />allow shared layouts with changing inner content. - A
path="*"route handles all unmatched URLs for a custom 404 page.
The next topic introduces performance optimization techniques — useMemo and useCallback — for preventing unnecessary re-renders and improving application speed.
