How to use React Router DOM

Niraj Narkhede - Aug 23 - - Dev Community

Introduction

Welcome to our in-depth tutorial on React Router DOM! If you're a UI developer looking to enhance your React applications with dynamic routing capabilities, you've come to the right place. React Router DOM is a powerful library that allows you to create single-page applications with multiple views, all while maintaining a smooth and seamless user experience.

In this comprehensive guide, we'll walk you through everything you need to know about React Router DOM, from basic concepts to advanced techniques. Whether you're new to React or an experienced developer looking to level up your skills, this tutorial will provide you with the knowledge and practical examples you need to implement routing in your React applications effectively.

So, let's dive in and explore the world of React Router DOM together!

Getting Started with React Router DOM

What is React Router DOM?

React Router DOM is a popular routing library for React applications. It allows you to create dynamic, client-side routing in your single-page applications (SPAs). With React Router DOM, you can easily manage different views and components based on the current URL, providing a seamless navigation experience for your users.

Installing React Router DOM

Before we begin implementing routing in our React application, we need to install the React Router DOM package. Open your terminal and navigate to your project directory, then run the following command:

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

This will install the latest version of React Router DOM in your project.

Basic Setup

To start using React Router DOM in your application, you need to import the necessary components and wrap your main application component with the BrowserRouter component. Here's a basic example of how to set up React Router DOM in your index.js file:

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode

Now that we have the basic setup in place, let's explore the core components of React Router DOM and how to use them effectively.

Core Components of React Router DOM

Routes and Route

The Routes and Route components are the building blocks of React Router DOM. They allow you to define the different paths and components that should be rendered for each route in your application.

Here's an example of how to use these components:

import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
import Contact from './components/Contact';

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

export default App;
Enter fullscreen mode Exit fullscreen mode

In this example, we've defined three routes: the home page ("/"), an about page ("/about"), and a contact page ("/contact"). Each route is associated with a specific component that will be rendered when the corresponding URL is accessed.

Link Component

The Link component is used to create navigation links in your application. It's an essential part of React Router DOM as it allows users to move between different views without triggering a full page reload.

Here's how you can use the Link component:

import React from 'react';
import { Link } from 'react-router-dom';

function Navigation() {
  return (
    <nav>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
        <li><Link to="/contact">Contact</Link></li>
      </ul>
    </nav>
  );
}

export default Navigation;
Enter fullscreen mode Exit fullscreen mode

NavLink Component

The NavLink component is similar to Link, but it provides additional functionality for styling active links. This is particularly useful for creating navigation menus where you want to highlight the current active page.

Here's an example of how to use NavLink:

import React from 'react';
import { NavLink } from 'react-router-dom';

function Navigation() {
  return (
    <nav>
      <ul>
        <li>
          <NavLink to="/" style={({ isActive }) => isActive ? { color: 'red' } : undefined}>
            Home
          </NavLink>
        </li>
        <li>
          <NavLink to="/about" style={({ isActive }) => isActive ? { color: 'red' } : undefined}>
            About
          </NavLink>
        </li>
        <li>
          <NavLink to="/contact" style={({ isActive }) => isActive ? { color: 'red' } : undefined}>
            Contact
          </NavLink>
        </li>
      </ul>
    </nav>
  );
}

export default Navigation;
Enter fullscreen mode Exit fullscreen mode

In this example, we're using the isActive prop to apply a red color to the active link.

Advanced Routing Techniques

Now that we've covered the basics, let's explore some more advanced routing techniques that you can implement using React Router DOM.

Nested Routes

Nested routes allow you to create more complex routing structures within your application. This is particularly useful for creating layouts with shared components or for organizing related routes.

Here's an example of how to implement nested routes:

import React from 'react';
import { Routes, Route, Outlet } from 'react-router-dom';
import Header from './components/Header';
import Footer from './components/Footer';
import Home from './components/Home';
import About from './components/About';
import Services from './components/Services';
import ServiceDetails from './components/ServiceDetails';

function Layout() {
  return (
    <div>
      <Header />
      <Outlet />
      <Footer />
    </div>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<Layout />}>
        <Route index element={<Home />} />
        <Route path="about" element={<About />} />
        <Route path="services" element={<Services />} />
        <Route path="services/:id" element={<ServiceDetails />} />
      </Route>
    </Routes>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

In this example, we've created a Layout component that includes a header and footer. The Outlet component is used to render the child routes within the layout.

Dynamic Routes and URL Parameters

Dynamic routes allow you to create flexible paths that can handle variable segments. This is useful for scenarios where you need to display detailed information about a specific item, such as a product page or user profile.

Here's an example of how to use dynamic routes and access URL parameters:

import React from 'react';
import { useParams } from 'react-router-dom';

function ProductDetails() {
  const { productId } = useParams();

  return (
    <div>
      <h1>Product Details</h1>
      <p>You are viewing product with ID: {productId}</p>
    </div>
  );
}

export default ProductDetails;
Enter fullscreen mode Exit fullscreen mode

To use this component, you would define a route like this:

<Route path="/products/:productId" element={<ProductDetails />} />
Enter fullscreen mode Exit fullscreen mode

Programmatic Navigation

Sometimes you need to navigate programmatically based on certain conditions or user actions. React Router DOM provides the useNavigate hook for this purpose.

Here's an example of how to use useNavigate:

import React from 'react';
import { useNavigate } from 'react-router-dom';

function LoginForm() {
  const navigate = useNavigate();

  const handleSubmit = (event) => {
    event.preventDefault();
    // Perform login logic here
    // If login is successful, navigate to the dashboard
    navigate('/dashboard');
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* Form fields */}
      <button type="submit">Login</button>
    </form>
  );
}

export default LoginForm;
Enter fullscreen mode Exit fullscreen mode

Handling Route Parameters and Query Strings

React Router DOM provides powerful tools for working with route parameters and query strings, allowing you to create dynamic and flexible routing solutions.

Route Parameters

We've already seen how to use route parameters with the useParams hook. Let's explore this further with a more complex example:

import React from 'react';
import { useParams } from 'react-router-dom';

function BlogPost() {
  const { category, postId } = useParams();

  return (
    <div>
      <h1>Blog Post</h1>
      <p>Category: {category}</p>
      <p>Post ID: {postId}</p>
    </div>
  );
}

export default BlogPost;
Enter fullscreen mode Exit fullscreen mode

To use this component, you would define a route like this:

<Route path="/blog/:category/:postId" element={<BlogPost />} />
Enter fullscreen mode Exit fullscreen mode

This allows you to create URLs like /blog/technology/123 or /blog/travel/456, with the category and post ID being dynamically extracted from the URL.

Query Strings

Query strings are useful for passing optional parameters to your routes. React Router DOM provides the useSearchParams hook to work with query strings.

Here's an example of how to use useSearchParams:

import React from 'react';
import { useSearchParams } from 'react-router-dom';

function ProductList() {
  const [searchParams, setSearchParams] = useSearchParams();
  const category = searchParams.get('category');
  const sortBy = searchParams.get('sortBy');

  return (
    <div>
      <h1>Product List</h1>
      <p>Category: {category || 'All'}</p>
      <p>Sort By: {sortBy || 'Default'}</p>
      <button onClick={() => setSearchParams({ category: 'electronics', sortBy: 'price' })}>
        Filter Electronics, Sort by Price
      </button>
    </div>
  );
}

export default ProductList;
Enter fullscreen mode Exit fullscreen mode

In this example, we're reading the category and sortBy parameters from the query string. We're also demonstrating how to update the query string using the setSearchParams function.

Protecting Routes and Handling Authentication

One common requirement in many applications is to protect certain routes based on user authentication status. React Router DOM can be used in conjunction with your authentication logic to create protected routes.

Here's an example of how you might implement protected routes:

import React from 'react';
import { Route, Navigate } from 'react-router-dom';

function ProtectedRoute({ element, isAuthenticated, ...rest }) {
  return (
    <Route
      {...rest}
      element={isAuthenticated ? element : <Navigate to="/login" replace />}
    />
  );
}

function App() {
  const [isAuthenticated, setIsAuthenticated] = React.useState(false);

  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/login" element={<Login setIsAuthenticated={setIsAuthenticated} />} />
      <ProtectedRoute
        path="/dashboard"
        element={<Dashboard />}
        isAuthenticated={isAuthenticated}
      />
    </Routes>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

In this example, we've created a ProtectedRoute component that checks if the user is authenticated. If they are, it renders the specified element; if not, it redirects them to the login page.

Handling 404 Pages and Redirects

React Router DOM makes it easy to handle 404 (Not Found) pages and implement redirects when necessary.

404 Pages

To create a 404 page, you can use the * path at the end of your route definitions:

import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
import NotFound from './components/NotFound';

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

export default App;
Enter fullscreen mode Exit fullscreen mode

In this example, the NotFound component will be rendered for any route that doesn't match the defined paths.

Redirects

Sometimes you may need to redirect users from one route to another. React Router DOM provides the Navigate component for this purpose:

import React from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import Home from './components/Home';
import OldPage from './components/OldPage';
import NewPage from './components/NewPage';

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/old-page" element={<Navigate to="/new-page" replace />} />
      <Route path="/new-page" element={<NewPage />} />
    </Routes>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

In this example, any user trying to access /old-page will be automatically redirected to /new-page.

Optimizing Performance with Code Splitting

As your application grows, you may want to implement code splitting to improve performance. React Router DOM works well with React's lazy loading feature, allowing you to load route components only when they're needed.

Here's an example of how to implement code splitting with React Router DOM:

import React, { Suspense, lazy } from 'react';
import { Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./components/Home'));
const About = lazy(() => import('./components/About'));
const Contact = lazy(() => import('./components/Contact'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
      </Routes>
    </Suspense>
  );
}

export default App;

In this example, we're using React's `lazy` function to dynamically import our components. The `Suspense` component is used to show a loading indicator while the component is being loaded.
Enter fullscreen mode Exit fullscreen mode

Conclusion

Congratulations! You've now completed a comprehensive tutorial on React Router DOM. We've covered everything from basic setup to advanced techniques like nested routes, dynamic routing, authentication, and code splitting. With this knowledge, you're well-equipped to implement robust routing solutions in your React applications.

Remember, the key to mastering React Router DOM is practice. Try implementing these concepts in your own projects, and don't be afraid to experiment with different routing structures and techniques. As you become more comfortable with React Router DOM, you'll find that it opens up new possibilities for creating dynamic and user-friendly web applications.

. . . . . . . . . . . . . . . . . . . . . . . .