Back to Blog
Lesson 16 of the Intermediate React: Hooks, State & Data Patterns course
ReactJune 26, 20263 min read

Introduction to React Router: Building Multi-Page SPAs

Learn how to use React Router to transform your dashboard into a seamless single-page application (SPA) with efficient routing and navigation.

reactreact routerroutingspanavigationfrontendjavascript

Previously in this course, we built a robust global state management system using Introduction to Context API: Avoiding Prop Drilling in React and Introduction to Custom Hooks: Master Abstraction in React. While our dashboard handles data well, it currently lives on a single page. Today, we’ll move beyond that limitation by implementing react router, the industry-standard library for handling navigation in a Single Page Application (SPA).

The Concept: Why Routing Matters in an SPA

In a traditional multi-page website, clicking a link triggers a browser request to the server, which then sends back an entirely new HTML document. This is slow and causes a jarring "flicker" as the page reloads.

In an SPA, the server sends one initial HTML file. When a user clicks a link, the JavaScript (React) intercepts the event, updates the URL, and swaps out the components currently visible on the screen. This makes your dashboard feel snappy and app-like. React Router acts as the "traffic controller," mapping URL paths to specific component trees.

Step 1: Installing and Configuring React Router

First, install the library in your project:

Bash
npm install react-router-dom

To set up routing, we need to wrap our application in a provider. This provider uses the History API under the hood to track where the user is and where they are going.

In your main.jsx (or index.js), wrap your App component with BrowserRouter:

JSX
import { BrowserRouter } from CE9178">'react-router-dom';

root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

Step 2: Defining Routes

Now that the router is listening, we define which components should render at which paths. We use the Routes component as a container and individual Route components to define the mapping.

JSX
import { Routes, Route } from CE9178">'react-router-dom';
import Dashboard from CE9178">'./Dashboard';
import Settings from CE9178">'./Settings';

function App() {
  return (
    <Routes>
      <Route path="/" element={<Dashboard />} />
      <Route path="/settings" element={<Settings />} />
    </Routes>
  );
}

When the URL ends in /, the Dashboard component renders. When it ends in /settings, the Settings component replaces it.

Step 3: Navigating Between Pages

Never use standard <a> tags for internal navigation in an SPA. An <a> tag will force a full browser reload, destroying your React state. Instead, use the Link component provided by React Router.

JSX
import { Link } from CE9178">'react-router-dom';

function Navigation() {
  return (
    <nav>
      <Link to="/">Dashboard</Link>
      <Link to="/settings">Settings</Link>
    </nav>
  );
}

The Link component renders an <a> tag in the DOM, but it prevents the default browser behavior and tells the router to update the view without a refresh.

Hands-on Exercise

  1. Add a new page component called Profile.jsx to your project.
  2. Add a new Route to your App.js mapping the path /profile to your Profile component.
  3. Update your navigation menu to include a link to the profile page.
  4. Verify that you can click between the Dashboard, Settings, and Profile without the page reloading.

Common Pitfalls

  • Forgetting the BrowserRouter: If you try to use Link or Routes outside of a BrowserRouter component, your application will throw an error. Ensure the provider is at the very top of your component tree.
  • The "Double Slash" Bug: Be careful with paths. While React Router is forgiving, standardizing your paths (e.g., always using /settings instead of settings/) prevents broken links as your app grows.
  • Using window.location: Avoid using the browser's native location API to change routes. React Router needs to manage the state internally; bypassing it will break the "back" button functionality.

Recap

We've successfully installed react-router-dom, wrapped our app in a BrowserRouter, defined a basic set of routes, and implemented navigation using the Link component. By avoiding full-page reloads, we've taken a significant step toward a high-performance dashboard.

Up next: We will learn how to handle dynamic data by implementing URL parameters, allowing us to display specific details for individual items in our dashboard.

Similar Posts