React Router
Workplace Context
In modern web development, Single Page Applications (SPAs) are prevalent. SPAs provide a fluid user experience by dynamically updating content without full page reloads. However, this means the browser’s default navigation (based on new HTML document requests) doesn’t work out-of-the-box. React Router is the de facto standard routing library for React, enabling developers to build SPAs with navigable “pages” or views, each associated with a unique URL. Understanding routing is crucial for creating intuitive and well-structured multi-view applications that users can easily navigate and share links to.
Learning Objectives
By the end of this lesson, you will be able to:
- Understand the role of client-side routing and React Router in SPAs.
- Install and set up React Router in a React project.
- Implement basic routing using
<BrowserRouter>
,<Routes>
, and<Route>
. - Create navigation links using the
<Link>
and<NavLink>
components. - Utilize the
useNavigate
hook for programmatic navigation. - Define and access route parameters using the
useParams
hook. - Be aware of advanced concepts like nested routes and layout components.
Introduction to React Router
React Router is a powerful routing library for React that allows you to manage navigation in your application. It enables you to define different “pages” or views and associate them with specific URLs. When a user navigates to a URL, React Router ensures the correct component is rendered without requiring a full page refresh from the server. This is known as client-side routing.
Installation
To start using React Router, you need to add it to your project. You can do this using npm or yarn:
npm install react-router-dom
or
yarn add react-router-dom
The react-router-dom
package includes bindings for using React Router in web applications.
Setting Up React Router
The first step is to make React Router’s context available to your component tree. This is typically done by wrapping your root application component (e.g., App.js
) with the <BrowserRouter>
component.
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
Core Components
React Router provides several core components to define your application’s routing structure.
<BrowserRouter>
<BrowserRouter>
uses the HTML5 History API (pushState
, replaceState
, and the popstate
event) to keep your UI in sync with the URL. As shown above, it should typically wrap your entire application.
<Routes>
The <Routes>
component is a container for a collection of <Route>
components. It intelligently picks the best <Route>
to render based on the current URL. When the location changes, <Routes>
looks through all its child <Route>
elements to find the best match and renders that branch of the UI.
<Route>
A <Route>
component defines a mapping between a URL path and a React component that should be rendered when that path is matched.
path
prop: A string representing the URL path to match (e.g.,"/about"
,"/users/:userId"
).element
prop: The React element/component to render when the path matches (e.g.,<AboutPage />
).
import React from 'react';
import { Routes, Route, Link } from 'react-router-dom';
// Placeholder components for demonstration
const HomePage = () => <h2>Home Page</h2>;
const AboutPage = () => <h2>About Page</h2>;
const ContactPage = () => <h2>Contact Page</h2>;
const NotFoundPage = () => <h2>404 - Page Not Found</h2>;
function App() {
return (
<div>
<nav>
{/* Navigation links will be added here */}
</nav>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contact" element={<ContactPage />} />
<Route path="*" element={<NotFoundPage />} /> {/* Fallback for unmatched routes */}
</Routes>
</div>
);
}
export default App;
In the example above, path="*"
acts as a catch-all route, often used for displaying a “404 Not Found” page.
Navigation
React Router provides components and hooks for navigating between routes.
<Link>
Component
The <Link>
component is the primary way to allow users to navigate around your application. It renders an <a>
tag with a proper href
attribute, but it handles the navigation client-side.
to
prop: A string or object representing the target path (e.g.,"/profile"
,{{ pathname: '/profile', search: '?sort=name' }}
).
// Inside your App.js or a Navigation component
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</nav>
<NavLink>
Component
<NavLink>
is a special type of <Link>
that can style itself as “active” when its to
prop matches the current URL. This is useful for highlighting the current page in a navigation menu.
It accepts style
and className
props that can be functions. These functions receive an object with an isActive
boolean property.
import { NavLink } from 'react-router-dom';
// ...
<NavLink
to="/messages"
style={({ isActive }) => ({
color: isActive ? 'red' : 'black',
})}
>
Messages
</NavLink>
<NavLink
to="/tasks"
className={({ isActive }) => isActive ? 'active-link' : 'inactive-link'}
>
Tasks
</NavLink>
useNavigate
Hook
The useNavigate
hook gives you access to a function that you can use to navigate programmatically, for instance, after a form submission or a state change.
import { useNavigate } from 'react-router-dom';
function MyComponent() {
const navigate = useNavigate();
const handleSubmit = () => {
// ... perform some action
navigate('/dashboard'); // Navigate to /dashboard
};
const goToPrevious = () => {
navigate(-1); // Navigate to the previous page in history
}
return (
<div>
<button onClick={handleSubmit}>Submit and Go to Dashboard</button>
<button onClick={goToPrevious}>Go Back</button>
</div>
);
}
Route Parameters
Often, you need to capture dynamic segments in the URL, like a user ID or a product slug. React Router allows you to define route parameters in your path
prop.
Example: /users/:userId
where :userId
is the parameter.
useParams
Hook
The useParams
hook returns an object of key/value pairs of URL parameters. Use it to access the matched parameters for the current <Route>
.
// ... other imports
import { useParams } from 'react-router-dom';
const UserProfilePage = () => {
const { userId } = useParams(); // userId matches :userId in the path
return <h2>User Profile: {userId}</h2>;
};
function App() {
// ...
return (
// ...
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contact" element={<ContactPage />} />
<Route path="/users/:userId" element={<UserProfilePage />} /> {/* Dynamic route */}
<Route path="*" element={<NotFoundPage />} />
</Routes>
// ...
);
}
If the URL is /users/123
, useParams()
in UserProfilePage
would return { userId: "123" }
. Note that URL parameters are always strings.
Advanced Concepts
React Router is very powerful and offers more advanced features that you might explore as your application grows:
- Nested Routes: Allows you to define routes that are children of other routes. This is useful for creating complex UI layouts where parts of the UI (like a sidebar) are shared across multiple sub-views. An
<Outlet />
component is used in parent routes to render their child route elements. - Layout Components (Layout Routes): A common pattern where a parent route acts as a layout wrapper (e.g., containing a header, footer, and navigation) and renders child routes within its structure using
<Outlet />
. - Protected Routes (Authentication): Implementing routes that require user authentication before they can be accessed.
- Search Parameters (
useSearchParams
): For reading and modifying the query string in the URL. - Location (
useLocation
): Provides information about the current URL (pathname, search, hash).
These concepts build upon the fundamentals covered in this lesson and are key to building sophisticated SPAs.
Activity 1: Build a Basic Multi-Page Application
Objective: Create a simple React application with Home, About, and Products pages using React Router.
Instructions:
- Set up a new React project or use an existing one.
- Install
react-router-dom
. - Create three components:
HomePage
,AboutPage
, andProductsPage
. - In your main
App
component:- Wrap your application with
<BrowserRouter>
. - Set up a navigation bar using
<Link>
components to navigate between these pages. - Define routes using
<Routes>
and<Route>
to render the appropriate component for/
,/about
, and/products
.
- Wrap your application with
- Ensure clicking the links correctly changes the view without a full page reload.
Activity 2: Implement Route Parameters for Product Details
Objective: Extend the previous application to display details for a specific product using route parameters.
Instructions:
- Create a
ProductDetailPage
component. - Modify the
ProductsPage
component:- Display a list of sample products (e.g., “Product 1”, “Product 2”).
- Each product name should be a
<Link>
that navigates to a unique URL for that product, like/products/1
,/products/2
.
- In your
App
component, add a new route:<Route path="/products/:productId" element={<ProductDetailPage />} />
. - In the
ProductDetailPage
component:- Use the
useParams
hook to extract theproductId
from the URL. - Display the
productId
(e.g., “Details for Product: [productId]”).
- Use the
- Verify that navigating to a product detail URL shows the correct product ID.
Knowledge Check
What is the primary purpose of React Router in a Single Page Application (SPA)?
- Select an answer to view feedback.
Which set of components is essential for defining basic routes in React Router?
- Select an answer to view feedback.
What is the React Router component used to create navigation links that enable client-side transitions?
- Select an answer to view feedback.
Which hook is used for programmatic navigation in React Router (e.g., navigating after a form submission)?
- Select an answer to view feedback.
How do you access dynamic segments from the URL path (e.g., a user ID from '/users/:userId') within a component rendered by a <Route>?
- Select an answer to view feedback.
In React Router v6, how do you typically define a 'catch-all' or '404 Not Found' route?
- Select an answer to view feedback.
Summary
React Router is an essential library for building SPAs with React. It allows you to create a rich, navigable user experience by mapping URLs to specific components. Key takeaways include:
- Wrapping your app in
<BrowserRouter>
. - Using
<Routes>
to define a collection of possible routes. - Defining individual routes with
<Route path="..." element={...} />
. - Navigating with
<Link>
(declarative) anduseNavigate
(programmatic). - Accessing dynamic URL segments with
useParams
.
Mastering these concepts will enable you to build well-structured and user-friendly React applications.
References
Additional Resources
- React Router 7 Tutorial - A comprehensive written guide with examples.
- React Router Examples - Official examples showcasing various features and patterns.