Introduction
Single Page Applications (SPAs) are web applications or websites that load a single HTML page and update it dynamically when a user interacts with the app. In contrast, the traditional web apps require full-page reloads on almost every single click of the user.
The SPAs are widely popular nowadays due to their ability to provide a smooth and seamless user experience. React, one of the most popular JavaScript libraries for building user interfaces, is frequently used to create SPAs. However, managing different pages or views in an SPA can become challenging as your application grows. This is where React Router comes handy.
In following article, we’ll explore how to use React Router and how it can help in building SPAs, with practical code examples along the way.
What is React Router and React Router DOM?
React Router
React Router is a popular library for managing routing in React applications. It enables developers to map different URLs to specific components, allowing users to navigate between views without reloading the entire page. With React Router, you can easily create routes, pass parameters, handle navigation, and redirect users
React Router DOM:
React Router DOM is also a library that helps developers create and manage routing in a React web applications.
Why Use React Router for SPAs?
React Router is perfect for SPAs because it offers several key features:
- Dynamic Routing: It allows you to define routes dynamically and respond to changes in the URL.
- Browser and Hash History: You can configure it to use either browser history (for cleaner URLs) or hash history (for simpler implementation).
- Nested Routes: React Router supports nested routes, allowing you to build complex applications with hierarchical structures.
- Parameterized Routes: It allows routes to handle dynamic segments, such as user IDs or post slugs.
Getting Started with React Router
Before you start using React Router, ensure that you have it installed in your React project. It can be installed either using npm or yarn:
npm install react-router-dom
Once the installation is complete, you can import the necessary components from react-router-dom and start building routes.
Setting Up Basic Routes
The most common components used in React Router are:
BrowserRouter
Browser Router
is a parent component that wraps the entire app to enable routing. All routes in an application must be wrapped within the BrowserRouter
. It stores the current location in the browser’s address bar using clean URLs and navigates using the browser’s built-in history stack.
You need to import BrowserRouter from the react-router-dom in your App.jsx file.
import { BrowserRouter} from "react-router-dom";
function App() {
return (
<BrowserRouter>
</BrowserRouter>
);
}
export default App;
It also has an attribute called basename which is used to set the base URL for all the routes in a web application
<BrowserRouter basename="/order">
</BrowserRouter>
Routes
In the former version of React Router, a switch was used. The Routes is a replacement for switch. It defines multiple route paths for your application. It also serves a parent component and renders the first matching child route.
In order to declare routes, you need to import Routes
from react-router-dom
and place it after the BrowserRouter
component.
import { BrowserRouter, routes } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
</Routes>
</BrowserRouter>
);
}
export default App;
Route
Route is used to define individual routes for different components. It is a child component which contains two attributes: path and element. The attribute path can be any path name, whereas the element attribute is the React component that should be rendered on that path.
There can be as many routes as the application needs. All routes must be declared inside the Routes component. Let’s assume that we have two pages “Home” and “About” in the “pages” directory/folder of our app.
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home/>}/>
<Route path="about" element={<About/>}/>
</Routes>
</BrowserRouter>
);
}
export default App;
Link
The Link creates links to navigate between different routes. It is similar to the href attribute of <a> tag in HTML. It has a to attribute that specifies where Link will take the user on click. The Links are often seen in the Navbar component.
Here’s an example of a simple React application with routing:
import { Link } from "react-router-dom";
export default function PageNav() {
return (
<>
<Link to="/">Home</Link>
<Link to="/pricing">Pricing</Link>
</>
);
}
Build Single Page Application
To better understand how to use React Router, here’s an example of a simple React application with routing:
import React from 'react';
import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-dom';
// Components for different pages
function Home() {
return <h2>Welcome to the Home Page</h2>;
}
function About() {
return <h2>About Us</h2>;
}
function Contact() {
return <h2>Contact Us</h2>;
}
function App() {
return (
<Router>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Router>
);
}
export default App;
In this example:
- The Router component wraps the application to manage navigation.
- Routes contain individual Route elements, each mapping a path to a component.
- With the help of Link elements users can navigate between pages without reloading.
In continuation to our discussion on how to use React Router, we’ll next see how we can handle dynamic route.
Handling Dynamic Routes
Dynamic routes play an important role in creating more advanced SPAs. For instance, if you are building a blog, you may need a route to display individual posts based on an ID or slug.
Here’s an example that handles dynamic routes:
import React from 'react';
import { BrowserRouter as Router, Routes, Route, useParams } from 'react-router-dom';
function Post() {
const { id } = useParams(); // Extracting the route parameter
return <h2>Displaying post with ID: {id}</h2>;
}
function App() {
return (
<Router>
<Routes>
<Route path="/post/:id" element={<Post />} />
</Routes>
</Router>
);
}
export default App;
Here:
- The route “/post/:id” handles dynamic parameters.
- useParams() is a React Router hook that extracts route parameters, allowing you to access them in the component.
Nested Routes
Sometimes, you need to have routes that are nested within other routes, such as a user profile page that has subpages for “Settings” and “Orders.” React Router allows you to define nested routes by placing routes within a parent component.
Here’s how you can do it:
import React from 'react';
import { BrowserRouter as Router, Routes, Route, Link, Outlet } from 'react-router-dom';
function User() {
return (
<div>
<h2>User Profile</h2>
<nav>
<ul>
<li><Link to="settings">Settings</Link></li>
<li><Link to="orders">Orders</Link></li>
</ul>
</nav>
<Outlet /> {/* Renders nested routes here */}
</div>
);
}
function Settings() {
return <h2>Account Settings</h2>;
}
function Orders() {
return <h2>Order History</h2>;
}
function App() {
return (
<Router>
<Routes>
<Route path="user" element={<User />}>
<Route path="settings" element={<Settings />} />
<Route path="orders" element={<Orders />} />
</Route>
</Routes>
</Router>
);
}
export default App;
In this example:
- Outlet acts as a placeholder for nested components.
- Sub-routes like
"/user/settings"
and"/user/orders"
are nested within theUser
route.
Redirecting and Navigation
Sometimes, you may want to redirect users or programmatically navigate to a different route. React Router provides components like Navigate and hooks like useNavigate
to accomplish this. Let’s us further explore how to use React Router by understanding redirection and navigation.
Example: Redirecting with Navigate
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
function OldPage() {
return <Navigate to="/newpage" />;
}
function NewPage() {
return <h2>This is the new page!</h2>;
}
function App() {
return (
<Router>
<Routes>
<Route path="/oldpage" element={<OldPage />} />
<Route path="/newpage" element={<NewPage />} />
</Routes>
</Router>
);
}
export default App;
Here, if the user tries to visit "/oldpage"
, they will be automatically redirected to "/newpage"
.
Example: Navigating Programmatically with useNavigate
import { BrowserRouter as Router, Routes, Route, useNavigate } from 'react-router-dom';
function Home() {
const navigate = useNavigate();
function handleClick() {
navigate('/about');
}
return (
<div>
<h2>Welcome to the Home Page</h2>
<button onClick={handleClick}>Go to About Page</button>
</div>
);
}
function About() {
return <h2>About Us</h2>;
}
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Router>
);
}
export default App;
In this example, clicking the button will programmatically navigate the user to the /about
page.
Conclusion
Thus, the process of building Single Page Applications (SPAs) can be easily simplified with the help of React Router. It allows the developers to manage multiple views within a React application. I hope, the above guide will give you an idea how to use React Router in SPAs.
By using dynamic and nested routes, as well as implementing navigation and redirection, you can easily build sophisticated, multi-view applications that feel fast and responsive. Mastering React Router is very essential for improving navigation and user experience whether you’re building a small project or a large-scale application.
P.S.: If you are curious how Lazy Loading in React help in providing users with a seamless experience, read here: What is Lazy Loading in React? A Beginner Guide to Implementation of Lazy Loading