The Ultimate Guide to Building Single-Page Applications with React Router v6

The Ultimate Guide to Building Single-Page Applications with React Router v6

Have you ever wondered what the difference is between React Router and React Router DOM? If so, you're not alone. In fact, the answer might surprise you: there is no difference!

Okay, that's not entirely true. Technically speaking, React Router is the core routing library for React, while React Router DOM is a wrapper around React Router that adds support for the DOM (Document Object Model). But in practical terms, React Router and React Router DOM are often used interchangeably, and it's easy to see why.

After all, both React Router and React Router DOM allow you to build dynamic, client-side routing in your React applications. They both provide a declarative API for defining routes and navigation, and they both work seamlessly with React's component-based architecture. So why the distinction?

In this blog post, we'll focus on React Router DOM, which is the more commonly used package for web applications. We'll explore the new features and functionality introduced in version 6, and we'll provide examples and best practices for using React Router DOM to build scalable, dynamic web applications.

React Router is one of the most popular libraries in the React ecosystem. It is a powerful routing library that helps you handle navigation in your React applications. React Router v6 is the latest version of the React Router library, which was released in October 2021. In this blog post, we will explore React Router v6 and its important hooks with code examples.

Getting Started with React Router v6:

To get started with React Router v6, you need to install it using npm or yarn. Here is the command to install it using npm:

npm install react-router-dom@next

Once you have installed the React Router v6 library, you can import the necessary components and hooks from the react-router-dom package:

import { BrowserRouter, Routes, Route, Link, useNavigate } from 'react-router-dom';

The BrowserRouter component is the top-level component that you need to wrap around your application. It provides the routing functionality to your application. The Routes component is used to define the routing hierarchy of your application, and the Route component is used to define individual routes. The Link component is used to create links between different pages in your application, and the useNavigate hook is used to programmatically navigate to different pages.

Defining Routes in React Router v6:

In React Router v6, you define routes using the Routes component. The Routes component is similar to the Switch component in React Router v5. It renders the first matching Route component based on the current URL.

Here is an example of how to define routes in React Router v6:

function App() {
  return (
    <BrowserRouter>
      <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 />}
/>
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

In this example, we define three routes for the Home, About, and Contact pages. We also define a fallback route (path="*") that will be rendered when none of the other routes match the current URL. The element prop is used to specify the component that should be rendered when the route matches the current URL.

Navigating between Routes in React Router v6:

In React Router v6, you can navigate between routes using the Link component or the useNavigate hook. The Link component is used to create links between different pages in your application, while the useNavigate hook is used to programmatically navigate to different pages.

Here is an example of how to use the Link component to navigate between routes:

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

In this example, we create links to the About and Contact pages using the Link component. When the user clicks on one of these links, React Router will automatically update the URL and render the corresponding route.

Here is an example of how to use the useNavigate hook to programmatically navigate to a different page:

function Contact() {
  const navigate = useNavigate();
  function handleSubmit(event) {
    event.preventDefault();
    navigate('/thankyou');
  }
  return (
    <div>
      <h1>Contact Us</h1>
      <form onSubmit={handleSubmit}>
        <label htmlFor="name">Name:</label>
        <input type="text" id="name" name="name" required />

        <label htmlFor="email">Email:</label>
        <input type="email" id="email" name="email" required />

        <button type="submit">Submit</button>
      </form>
    </div>
  );
}

In this example, we use the useNavigate hook to programmatically navigate to the /thankyou route when the user submits the contact form.

React Router v6 Hooks:

React Router v6 provides several hooks that you can use to access the routing functionality in your components.

  1. useParams(): This hook returns an object containing key/value pairs of the dynamic segments in the current URL.

    here's an example of how to use the useParams hook with a sample URL:

    Suppose the URL for our component is /users/123/posts/456. Here's what the URL looks like:

     /users/123/posts/456
    

    In this URL, 123 and 456 are dynamic segments that represent the userId and postId parameters, respectively.

    To access these parameters in our component using the useParams hook, we can do the following:

     import { useParams } from 'react-router-dom';
    
     function PostPage() {
       const { userId, postId } = useParams();
    
       return (
         <div>
           <h1>User ID: {userId}</h1>
           <h2>Post ID: {postId}</h2>
         </div>
       );
     }
    

    In this example, we're calling the useParams hook to access the userId and postId parameters from the URL. We then use these parameters in our component to display the user and post IDs.

    If the URL is /users/123/posts/456, the output of this component would be:

     User ID: 123
     Post ID: 456
    
  1. useLocation(): This hook returns an object containing information about the current URL, such as the pathname, search parameters, and hash. Here is an example:
function PageHeader() {
  const location = useLocation();

  return (
    <div>
      <h1>{location.pathname}</h1>
    </div>
  );
}

In this example, we use the useLocation hook to display the current pathname in the page header.

  1. useNavigate(): This hook returns a function that you can use to programmatically navigate to a different route. Here is an example:
function LoginPage() {
  const navigate = useNavigate();

  function handleLogin() {
    // perform login logic here
    navigate('/dashboard');
  }

  return (
    <div>
      <h1>Login Page</h1>
      <button onClick={handleLogin}>Login</button>
    </div>
  );
}

In this example, we use the useNavigate hook to programmatically navigate to the /dashboard route when the user clicks the Login button.

  1. useRoutes: useRoutes is a hook that allows you to define your routes in a nested configuration, similar to how you might define nested components in React. This can make your code easier to read and maintain, particularly if you have a complex routing structure.

     import { useRoutes } from 'react-router-dom';
    
     const routes = [
       {
         path: '/',
         element: <Home />,
         children: [
           { path: 'about', element: <About /> },
           { path: 'contact', element: <Contact /> },
           { path: '*', element: <NotFound /> }
         ]
       }
     ];
    
     function App() {
       const routing = useRoutes(routes);
    
       return routing;
     }
    

    In this example, we define our routes as a nested array of objects, with each object representing a route or a group of routes. The path property specifies the URL path for the route, and the element property specifies the component to render for that route.

    The useRoutes hook takes our routes configuration as a parameter and returns a component that can be rendered in our application. This component will automatically handle routing based on the current URL path.

Conclusion
React Router v6 is a powerful routing library that can help you handle navigation in your React applications. In this blog post, we explored how to get started with React Router v6, how to define routes, and how to navigate between routes using the Link component and the useNavigate hook. We also covered some of the important hooks provided by React Router v6, such as useParams, useLocation, and useNavigate. Hopefully, this blog has given you a good understanding of React Router v6 and its important hooks.

Did you find this article valuable?

Support Insightful Bytes by becoming a sponsor. Any amount is appreciated!