So far, all your React apps have been single-page applications with one URL. But real apps need multiple pages: a home page, about page, user profile, dashboard, and more. React Router is the standard library for adding navigation to React apps. It lets you create multiple "pages" that change the URL and browser history, all without page reloads. Let's learn how to build multi-page React applications! πΊοΈ
What Is Routing?
Routing is the process of determining what content to display based on the URL:
Traditional Multi-Page App (Server-Side Routing):
/ β Server sends home.html
/about β Server sends about.html (full page reload!)
/contact β Server sends contact.html (full page reload!)
Single-Page App (Client-Side Routing):
/ β React renders <Home />
/about β React renders <About /> (no page reload!)
/contact β React renders <Contact /> (no page reload!)Client-Side Routing Benefits:
- Fast navigation - No full page reloads
- Smooth transitions - Can animate between pages
- Maintains state - App state persists
- Better UX - Feels like a native app
- Browser history - Back/forward buttons work
- Shareable URLs - Each page has unique URL
React Without Router
Without a router, you'd need to manually manage which component to show:
// β Manual routing - Don't do this!
function App() {
const [page, setPage] = React.useState('home')
const renderPage = () => {
switch (page) {
case 'home':
return <Home />
case 'about':
return <About />
case 'contact':
return <Contact />
default:
return <Home />
}
}
return (
<div>
<nav>
<button onClick={() => setPage('home')}>Home</button>
<button onClick={() => setPage('about')}>About</button>
<button onClick={() => setPage('contact')}>Contact</button>
</nav>
{renderPage()}
</div>
)
}
// Problems:
// 1. URL doesn't change - can't bookmark or share
// 2. Browser back button doesn't work
// 3. No page history
// 4. Have to manage state manually
// 5. No nested routes
// 6. Can't use browser navigationThe Solution: React Router
React Router handles all the routing complexity for you:
// β
With React Router - Much better!
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'
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>
)
}
// Benefits:
// β
URL changes automatically
// β
Browser back/forward works
// β
History maintained
// β
Shareable URLs
// β
Nested routes supported
// β
Works with browser navigationInstalling React Router
# Install React Router
npm install react-router-dom
# This installs React Router DOM version 6
# (The latest and recommended version)βΉοΈ React Router Versions
React Router v6 is the current version (released 2021)
Major differences from v5:
β’ <Switch> β <Routes>
β’ component prop β element prop
β’ Nested routes work differently
β’ Simpler and more powerful API
This tutorial covers v6 (the modern version)
Basic Setup
Step 1: Wrap App in BrowserRouter
// index.js or main.jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
)
// BrowserRouter provides routing context to entire appStep 2: Create Page Components
// pages/Home.jsx
function Home() {
return (
<div>
<h1>Home Page</h1>
<p>Welcome to our website!</p>
</div>
)
}
// pages/About.jsx
function About() {
return (
<div>
<h1>About Page</h1>
<p>Learn more about us here.</p>
</div>
)
}
// pages/Contact.jsx
function Contact() {
return (
<div>
<h1>Contact Page</h1>
<p>Get in touch with us.</p>
</div>
)
}
export { Home, About, Contact }Step 3: Define Routes
// App.jsx
import { Routes, Route, Link } from 'react-router-dom'
import { Home, About, Contact } from './pages'
function App() {
return (
<div>
{/* Navigation */}
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/contact">Contact</Link>
</nav>
{/* Routes */}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
)
}
export default AppCore React Router Components
1. BrowserRouter
import { BrowserRouter } from 'react-router-dom'
// Wrap your entire app
<BrowserRouter>
<App />
</BrowserRouter>
// What it does:
// - Keeps UI in sync with URL
// - Uses HTML5 history API
// - Provides routing context
// - Should be at top level (usually in index.js)
// Note: Only use one BrowserRouter per app!2. Routes and Route
import { Routes, Route } from 'react-router-dom'
<Routes>
{/* Each Route defines a path and what to render */}
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users" element={<Users />} />
</Routes>
// Routes:
// - Container for all Route components
// - Matches current URL to routes
// - Renders the first matching Route
// Route:
// - path: URL pattern to match
// - element: Component to render when matched
// Example URL matching:
// / β Renders <Home />
// /about β Renders <About />
// /users β Renders <Users />
// /not-found β Renders nothing (404)3. Link
import { Link } from 'react-router-dom'
// Basic link
<Link to="/about">About Us</Link>
// Link with styling
<Link to="/contact" className="nav-link">
Contact
</Link>
// What it does:
// - Renders an <a> tag
// - Prevents full page reload
// - Updates URL
// - Maintains app state
// - Updates browser history
// β Don't use regular <a> tags!
<a href="/about">About</a> // This causes full page reload!
// β
Use Link instead
<Link to="/about">About</Link> // This uses client-side routing4. NavLink (Link with Active State)
import { NavLink } from 'react-router-dom'
// NavLink automatically adds 'active' class when route matches
<nav>
<NavLink to="/">Home</NavLink>
<NavLink to="/about">About</NavLink>
<NavLink to="/contact">Contact</NavLink>
</nav>
// Custom active styling
<NavLink
to="/about"
className={({ isActive }) => isActive ? 'active-link' : 'link'}
>
About
</NavLink>
// With inline styles
<NavLink
to="/about"
style={({ isActive }) => ({
color: isActive ? 'red' : 'blue'
})}
>
About
</NavLink>
// Perfect for navigation menus!Interactive Demo
π‘ Tip: Edit the code above and click "Run" to see your changes
Complete Example
Here's a full working example with React Router:
// App.jsx
import { Routes, Route, Link, NavLink } from 'react-router-dom'
import './App.css'
// Page components
function Home() {
return (
<div className="page">
<h1>Home Page</h1>
<p>Welcome to our website!</p>
</div>
)
}
function About() {
return (
<div className="page">
<h1>About Us</h1>
<p>We build amazing React applications.</p>
</div>
)
}
function Services() {
return (
<div className="page">
<h1>Our Services</h1>
<ul>
<li>Web Development</li>
<li>Mobile Apps</li>
<li>Consulting</li>
</ul>
</div>
)
}
function Contact() {
return (
<div className="page">
<h1>Contact Us</h1>
<form>
<input type="email" placeholder="Your email" />
<textarea placeholder="Your message" />
<button type="submit">Send</button>
</form>
</div>
)
}
function NotFound() {
return (
<div className="page">
<h1>404 - Page Not Found</h1>
<p>The page you're looking for doesn't exist.</p>
<Link to="/">Go Home</Link>
</div>
)
}
// Main App component
function App() {
return (
<div className="app">
{/* Header with Navigation */}
<header>
<div className="logo">MyApp</div>
<nav>
<NavLink to="/" end>Home</NavLink>
<NavLink to="/about">About</NavLink>
<NavLink to="/services">Services</NavLink>
<NavLink to="/contact">Contact</NavLink>
</nav>
</header>
{/* Main Content */}
<main>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/services" element={<Services />} />
<Route path="/contact" element={<Contact />} />
<Route path="*" element={<NotFound />} />
</Routes>
</main>
{/* Footer */}
<footer>
<p>© 2024 MyApp. All rights reserved.</p>
</footer>
</div>
)
}
export default App.app {
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
background: #1e40af;
color: white;
}
.logo {
font-size: 1.5rem;
font-weight: bold;
}
nav {
display: flex;
gap: 1rem;
}
nav a {
color: white;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.25rem;
transition: background 0.2s;
}
nav a:hover {
background: rgba(255, 255, 255, 0.1);
}
nav a.active {
background: rgba(255, 255, 255, 0.2);
font-weight: bold;
}
main {
flex: 1;
padding: 2rem;
max-width: 1200px;
margin: 0 auto;
width: 100%;
}
.page {
animation: fadeIn 0.3s;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
footer {
padding: 1rem;
text-align: center;
background: #f3f4f6;
border-top: 1px solid #e5e7eb;
}404 Page (Catch-All Route)
Handle unknown routes with a catch-all 404 page:
import { Routes, Route, Link } from 'react-router-dom'
function NotFound() {
return (
<div>
<h1>404 - Page Not Found</h1>
<p>The page you're looking for doesn't exist.</p>
<Link to="/">Go back home</Link>
</div>
)
}
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
{/* Catch-all route - must be last! */}
<Route path="*" element={<NotFound />} />
</Routes>
)
}
// path="*" matches any URL that wasn't matched above
// Always put this route last!Key Takeaways
- React Router enables client-side routing in SPAs
- Install with
npm install react-router-dom - Wrap app in
<BrowserRouter> - Define routes with
<Routes>and<Route> - Use
<Link>for navigation (not<a>) <NavLink>adds active state automatically- Route matches
pathand renderselement - No page reloads when navigating
- Browser back/forward buttons work automatically
- Each route has its own unique URL
- Use
path="*"for 404 catch-all route - Put catch-all route last in Routes
- React Router v6 is the current version
What's Next?
You now understand the basics of React Router! You know how to set up routing, create routes, and navigate between pages.
In the next lesson, you'll learn about Routes and Navigation:
- Programmatic navigation with useNavigate
- Nested routes and layouts
- Index routes
- Route matching and priority
- Loading states and navigation feedback
Get ready to build more complex routing structures! π