DEV Community

Cover image for An Introduction to React Router: A Beginner’s Guide
DevvEmeka
DevvEmeka

Posted on • Updated on

An Introduction to React Router: A Beginner’s Guide

The React Router is a third-party library that is popularly used to add routing to a React application. On traditional websites, when a user clicks on a link or submits a form, the browser sends a request to the server for routing. But the React Router works as a single-page application (SPA). A single-page application handles all the browser's routing on the Frontend and doesn’t send additional requests to the server for a new page.

Routing is simply the ability to move between different parts of an application when a user enters a URL or clicks an element (link, button, icon, image, etc.). Routing plays an important role in building responsive and user-friendly web applications.

This article will teach you everything you need to know about adding React Router to a React application. You will learn about the React Router Library, how to install it, and the use case for it. In the process, we will build a simple React Application with the React Router library.

Prerequisites

This tutorial assumes that the reader has the following:

  • Node is installed on their local development machine.

  • Knowledge of using React.

  • Basic knowledge of HTML, CSS, and JavaScript.

What is React Router?

React Router is a declarative, component-based, client and server-side routing library for React. The React Router library allows users to navigate between web pages without reloading the page or interacting with the server. Since the React framework doesn’t come with in-built routing, React Router is the most popular solution for adding routing to a React application.

Getting Started  

Before we go deep into this article, I want to introduce you to some important terminologies that we will come across when using React Router in our project. Here are the terminologies we need to add React Router to our React application:

BrowserRouter: For React Router to work, it has to be aware and in control of your application’s location. The <BrowserRouter> component makes that possible when you wrap the entire application within it. Wrapping the entire application with <BrowserRouter> ensures the use of routes within it.

Routes: Whenever we have more than one route, we wrap them up in Routes. If the application’s location changes, Routes look through all its child Route to find the best match and render that branch of UI.

Route: Route(s) are objects passed to the router creation function. Route renders a component whenever a user navigates to the component path.

Link: The <Link> component allows the user navigate to another page. To navigate between pages, we pass the <Link> component a prop. The Link component is similar to the HTML <a> tag; the difference here is that the Link component only renders the UI and doesn’t reload the page.

NavLink: A <NavLink> is a special kind of <Link> that points to the location that is currently selected. It also provides useful context for assistive technology like screen readers.

Path: A path is a prop on the component that describes the pathname that the route should match. When a path is matched, a React component is rendered, and there will be a change in the UI.

Element: The element renders the UI when the route matches the browser URL.

Use Case of React Router

We will learn about implementing the React router in our project by creating a simple React application.
 
To create a React application using create-react-app, go to your preferred CMD and type:

npx create-react-app router-tutorial
Enter fullscreen mode Exit fullscreen mode

The command will create a React application called router-tutorial. Once the application has been successfully created, switch to the app directory using cd router-tutorial in your code editor terminal and run the command below:

npm start
Enter fullscreen mode Exit fullscreen mode

If the React application has been successfully created, you will be redirected to the React homepage in your browser when you navigate to your application's local host: localhost:3000.

Installing React Router

I mentioned earlier that React Router is an external library and not part of React itself. To use React Router in your application, you need to install it. To install React Router in your application, go to your code editor terminal, and in the root directory of your project, type:

npm install react-router-dom
Enter fullscreen mode Exit fullscreen mode

Now that the router package is installed, we may proceed with configuring the React Router library in our application. For this tutorial, I used React Router version 6.4.

Setting up React Router

To enable routing in our React application, we have to import the BrowserRouter module from react-router-dom inside the index.js file, then wrap the App.js component inside the BrowserRouter component.

// index.js
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>
);

Enter fullscreen mode Exit fullscreen mode

Wrapping <App /> with <BrowserRouter> will apply the React Router to the components where routing is needed. That is, if you want to route in your application, you have to wrap the <App /> application with <BrowserRouter>.

Rendering Routes

Now that we have successfully set up React Router, to implement routing in our application, we have to render a route (that is, all the pages or components we want to navigate in our browser). To render our routes, we will set up a route for every component in our application.

Here, we will create three components: Home.js, About.js, and User.js. To create these components, we will create a folder in our src folder with the name pages and create three files inside the folder: Home.js, About.js, and User.js. To render our route, we have to import the components we created at the top of the App.js file.

// App.js
import { Routes, Route} from "react-router-dom";

//imported components
import Home from "./pages/Home";
import About from "./pages/About";
import User from "./pages/User";

function App() {
  return (
      <>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/user" element={<User />} />
        </Routes>
      </>
  );
}

export default App

Enter fullscreen mode Exit fullscreen mode

In the code above, we imported Routes and Route from react-router-dom. We also imported the Home, About, and User components and wrapped the Route components inside our Routes component. We set up a Route component for every Route in our application, which are: Home, About, and User Route.

We also imported Routes and Route to our root component so they could be rendered. Each Route comes with two props, which are a path and an element, and they perform different functions. This is what they do:

Path: The role of path is to match the path with the URL in the browser. It identifies the path that the user wants to navigate to and navigates to the page. For example, if the path matches the browser URL, it navigates to the <about/> page.

Element: The element contains the component we want to navigate to. It contains the component we want the path to load. Note that the path and element must correspond for the route to work.

The path for the home page is usually set to backlash (/) or index. In this tutorial, we will use a backslash.

How to Navigate Routes with Links

Now that we have been able to set up and render routing in our application, we also need to enable users to navigate between pages in our application. For this example, we will navigate between pages in the navbar. To achieve this, we need to create Links within our application.

The <Link /> tag plays a similar role as the <a> tag in HTML. It enables smooth navigation to another page. To implement <Link /> in our application, we will create a file with the name navbar and import the file in App.js.

// App.js
import NavBar from "./component/NavBar";

function App() {
  return (
    <>
      <NavBar />
      <Routes>
        // ...
      </Routes>
    </>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Moving forward, we will add Links to the NavBar file we created.

// NavBar.js
import { Link } from "react-router-dom";

const NavBar = () => {
  return (
    <header>
      <nav>
        <ul>
          <li>
            <Link to='/'>Home</Link>
          </li>
          <li>
            <Link to='/about'>About</Link>
          </li>
          <li>
            <Link to='/user'>User</Link>
          </li>
        </ul>
      </nav>
    </header>
  );
};

export default NavBar;

Enter fullscreen mode Exit fullscreen mode

In the code snippet above, we imported Link from the react-router-dom and added a prop. To specify the path that the Link should navigate to, we pass the same path we specified when setting up our routes in the prop. When the user clicks on the link in the browser, the Link tag watches the path in the prop and displays the page if it matches the route.

Using Active Links to Navigate a Route

The NavLink adds an active Link to our current page. An active Link is the Link that a user is active on. With the active class, we can add styles to the active Link. The NavLink enables users to identify the exact page they are currently on by styling the Link with a background colour, text colour, underline, and other CSS styles.

// NavBar
import { NavLink } from "react-router-dom";

const NavBar = () => {
  return (
    <header>
      <nav>
        <ul>
          <li>
            <NavLink to='/'>Home</Link>
          </li>
          <li>
            <NavLink to='/about'>About</Link>
          </li>
          <li>
            <NavLink to='/user'>User</Link>
          </li>
        </ul>
      </nav>
    </header>
  );
};

export default NavBar;

Enter fullscreen mode Exit fullscreen mode

Similar to the Link tag, to implement NavLink, we imported NavLink from react-route-dom. To indicate an active page, we must style the active link. You can style the active link any way you like. Here is an example of how you can style the active link:

// index.css
ul li a {
  color: #0000FF;
}

ul li a:hover {
  color: #00a4ff;
}

ul li a.active {
  color: #add8e6;
}

Enter fullscreen mode Exit fullscreen mode

Setting up a 404 Page

If a user navigates to a URL that doesn’t exist, the user will get an error message: "No routes matched location." The error message shows that the page the user is trying to access doesn’t exist. We can fix this error by setting up a 404 page to handle invalid routes. Here is how to set up a 404 page:

// App.js
import { Routes, Route } from "react-router-dom";
import NotFound from "./component/NotFound";

const App = () => {
  return (
    <>
      <Routes>
        // ...
          <Route path="*" element={<NotFound />} />
      </Routes>
    </>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode

In the code above, we created a route with a path of "*" that will handle all the nonexistent routes and match them with the element of the component attached.

// NotFound.js
const NotFound = () => {
  return (
    <div style={{ padding: 20 }}>
      <h2>404: Page Not Found</h2>
    </div>
  );
};

export default NotFound;

Enter fullscreen mode Exit fullscreen mode

In the code above, we created a component with the name NotFound.js, and in it component, we added "404: page not found" which displays when a user navigates to a nonexistent route. You are free to add any description of your choice on the 404 page. In setting up the 404 page, you can add a Link to redirect the user to the homepage.

Navigating Programmatically in React Router

Programmatic navigation happens when a user performs an action that redirects or navigates them to another page. The action may involve the clicking of a button or link, or when a conditional statement in your code is triggered.

To navigate programmatically, first we need to import the useNavigate hook from react-router-dom. Secondly, we will declare the useNaviagte API by setting navigate to useNavigate(). Let's see an example of how we can navigate programmatically using an onClick event:

// Cat.js
import { useNavigate } from "react-router-dom"

function Cat() {
    const navigate = useNavigate();
  return (
    <div>
        <div>
            <h1>Male Apparel</h1>
        </div>
        <div>
        <button onClick={() => navigate("/new-arrival")}>
            New Arrival
        </button>
        </div>
    </div>
  )
}

export default Cat

Enter fullscreen mode Exit fullscreen mode

In the code above, if a user clicks on the button "New Arrival", it will trigger the onClick event and direct the user to the /new-arrival path. It’s important to note that we already created the <NewArrival /> file and imported its route in the App.js file, so when the user clicks on the button, they will navigate automatically to the /new-arrival route.

How to Configure Nested Routes

A nested route is a routing pattern in React Router where a route is nested as a child in another route. Usually, the parent route is used to wrap the child route, and both the parent and child route are rendered to the UI. A nested route enables multiple route to be displayed on the same web page.

In our example, we will set up a parent route /books and a child route /new-books. The parent route will be in charge of rendering the child route. Meaning that the /new-books path will be relative to the /books path, and both route will render on the same page.

To create a nested route, we will start by going to the App.js file and appending an /* to the parent route path. By appending an /* to the /books path, we're telling React Router that the <Books/> component has a nested route, and our parent path should match the nested route.

// App.js
import { Route, Routes } from "react-router-dom"
import Books from './component/Books'
import Home from './component/Home'

function App() {
  return (
    <>
      <Routes>
        <Route path='/' element={<Home />} />
        <Route path='/books/*' element={<Books />} />
      </Routes>
    </>
  )
}

export default App

Enter fullscreen mode Exit fullscreen mode

In order to match the parent route to the child route and render the /new-books route when the user is also on the /books route, we will embed the /new-books route inside the <Books/> component.

// Books.js
import React from 'react'
import { Route, Routes } from "react-router-dom"
import NewBooks from './NewBooks'

function Books() {
  return (
    <div>
      <div>
        <h1>Books,</h1>
        <p>This is the books page.</p>
      </div>

      <Routes>
        <Route path="new-books" element={<NewBooks />} />
      </Routes>  
    </div>
  )
}

export default Books

Enter fullscreen mode Exit fullscreen mode

At this point, the user can navigate to the /books route and also navigate to the /new-books route, and both components will display on the UI. When the nested route is rendered, it will look like this in the browser: /books/new-books. Although this method works quite well, there is another method for rendering nested routes, and it is done using the <outlet/> component.

Nesting Routes with Outlet

The <outlet/> component provides a simple approach to rendering nested route. Rather than nesting the child route in the parent component like this:

<div>
   <div>
     <h1>Books,</h1>
     <p>This is the books page.</p>
   </div>

   <Routes>
    <Route path="new-books" element={<NewBooks />} // nested route
   </Routes>  
</div>

Enter fullscreen mode Exit fullscreen mode

Rather than the option above, we will use the <Outlet/> component to render the nested route. Here is how to nest the child route using <Outlet/>:

 <div>
    <div>
      <h1>Books,</h1>
      <p>This is the books page.</p>
    </div>

    <Outlet /> // nested route
 </div>

Enter fullscreen mode Exit fullscreen mode

The <Outlet/> serves as a placeholder location where the nested route will be rendered. The <Outlet/> component tells the parent route where to render its children.

So let's explore how we can create a nested route using the <Outlet/> component. To understand how nested route and outlet work together, let's take an example:

// App.js
import { Route, Routes } from "react-router-dom"
import Books from './component/Books'
import NewBooks from './component/NewBooks'
import Home from './component/Home'
import NewArrival from './component/NewArrival'

function App() {
  return (
    <>
      <Routes>
        <Route path='/' element={<Home />} />
        <Route path="books" element={<Books />}>
          <Route path="new-books" element={<NewBooks />} /> 
        </Route>
        <Route path="new-arrival" element={<NewArrival />} />
      </Routes>
    </>
  )
}

export default App

Enter fullscreen mode Exit fullscreen mode

In the code above, first we imported the necessary components, and then we imported Route and Routes from react-router-dom in the App.js file. Still in the App.js file, we defined three route: the home page (‘/’), the books page (/books), the new-books page (/new-books), and the new-arrival page (/new-arrival).

To render the child route in the parent route as a nested route, we wrapped the /new-books route with the /books route. By wrapping the /new-books route with the /books route, the browser will render the /new-books route within the /books component.

To be able to use the <Outlet /> component to render a child route within the parent component, first we will import the <Outlet /> component at the top of the <Books /> component. Next, we will embed the child route within the parent component by using the <Outlet /> component to point to where to render the child route within the /books component:

// Books.js
import React from 'react'
import { Outlet } from "react-router-dom"

function Books() {
  return (
    <div>
      <div>
        <h1>Books,</h1>
        <p>This is the books page.</p>
      </div>
      <Outlet />
    </div>
  )
}

export default Books

Enter fullscreen mode Exit fullscreen mode

Conclusion 

The React router library provides a smooth and responsive way for routing and navigating between web pages. React Router also works as a single-page application, where we can move between web pages without reloading our application. The library should be your preferred choice if you choose to add routing to your React application. To learn more about advanced features in the React Router library, you can check out the React Router documentation for more information.

Top comments (0)