Simplifying Nested Routes in React Router

vikram-boominathan

Vikraman

Posted on May 24, 2024

Simplifying Nested Routes in React Router

Introduction

React Router v6 introduces a powerful and flexible way to manage routing in React applications. With features like nested routes, index routes, relative paths, NavLink, and Outlet components, it offers a seamless navigation experience. In this guide, we'll walk through setting up a React application with nested routes and explore these features in detail.

Key Concepts

1. Index Route
An index route is the default child route that renders when the parent route is matched but no other child routes are matched. It's typically used to display a default view or landing page for a section of your application.

In App.js, the index prop on a inside dashboard makes Profile the default component for /dashboard.

<Route path="dashboard" element={<Dashboard />}>
  <Route index element={<Profile />} />
  <Route path="settings" element={<Settings />} />
</Route>
Enter fullscreen mode Exit fullscreen mode

2. Nested Routes
In React, nested routes simply refer to a routing structure in which routes are included in other routes, resulting in a tree of routes. This concept is critical for developing applications with complex navigational structures because it allows you to create menus with multiple levels or sub-pages that can relate to the main page.

In simple terms, UI sharing between pages is easier.

<Routes>
        <Route path="/" element={<Layout />}>
          <Route index element={<Home />} />
          <Route path="dashboard" element={<Dashboard />}>
            <Route index element={<Profile />} />
            <Route path="settings" element={<Settings />} />
          </Route>
        </Route>
</Routes>

Enter fullscreen mode Exit fullscreen mode

3. NavLink
NavLink is a React component which allows us to navigate within a React application. It is similar to the Link component, but with additional features that make it ideal for creating navigational links with active styling.

When you use the end prop, NavLink is only considered active if the route matches the URL exactly. Without the end prop, NavLink can be active on any sub-path.

<NavLink to="/" end style={({ isActive }) => ({ color: isActive ? 'red' : 'black' })}>
  Home
</NavLink>
<NavLink to="dashboard" style={({ isActive }) => ({ color: isActive ? 'red' : 'black' })}>
  Dashboard
</NavLink>
Enter fullscreen mode Exit fullscreen mode

4. Outlet and Context
Outlet is a placeholder component for nested routes. It serves as a method for rendering child components or routes within a parent component.

Context can be passed down the route tree.This enables you to share data and functionality between route components.

The Outlet component renders the matched nested route. Outlet context is provided to share data between parent and child routes.

<Outlet context={{ user }} />
Enter fullscreen mode Exit fullscreen mode

5. useOutletContext

The library provides a hook called useContextOutlet that lets you access the closest component in your component hierarchy. When you need to access the outlet's context, this can be helpful.

import { useOutletContext } from 'react-router-dom';

const Profile = () => {
  const { user } = useOutletContext();
../
<p>Name: {user}</p>
../
Enter fullscreen mode Exit fullscreen mode

6. Relative Paths
In Dashboard, Link to="" navigates to the Profile component which is a index route and Link to="settings" navigates to the Settings component.

<Link to="">Profile</Link>
<Link to="settings">Settings</Link>
Enter fullscreen mode Exit fullscreen mode

Getting Started

First, create a new React application using create-react-app and install react-router-dom.

npx create-react-app react-router-example
cd react-router-example
npm install react-router-dom
Enter fullscreen mode Exit fullscreen mode

Setting Up Routes

In App.js, we'll define our routes using the Routes and Route components. We'll also create nested routes for the dashboard.

import React from 'react';
import { Routes, Route, BrowserRouter } from 'react-router-dom';
import Layout from './components/Layout';
import Home from './components/Home';
import Dashboard from './components/Dashboard';
import Profile from './components/Profile';
import Settings from './components/Settings';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Layout />}>
          <Route index element={<Home />} />
          <Route path="dashboard" element={<Dashboard />}>
            <Route index element={<Profile />} />
            <Route path="settings" element={<Settings />} />
          </Route>
        </Route>
      </Routes>
    </BrowserRouter>

  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Creating the Layout Component

The Layout component includes navigation links and an Outlet for nested routes.

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

const Layout = () => {
  return (
    <div>
      <nav>
        <ul>
          <li>
            <NavLink to="/" end style={({ isActive }) => ({ color: isActive ? 'red' : 'black' })}>
              Home
            </NavLink>
          </li>
          <li>
            <NavLink to="dashboard" style={({ isActive }) => ({ color: isActive ? 'red' : 'black' })}>
              Dashboard
            </NavLink>
          </li>
        </ul>
      </nav>
      <hr />
      <Outlet />
    </div>
  );
};

export default Layout;
Enter fullscreen mode Exit fullscreen mode

Home Component

The Home component is a simple functional component.

import React from 'react';

const Home = () => {
  return (
    <div>
      <h2>Home</h2>
      <p>Welcome to the home page!</p>
    </div>
  );
};

export default Home;

Enter fullscreen mode Exit fullscreen mode

Dashboard Component with Nested Routes

The Dashboard component includes links for its nested routes and an Outlet for rendering them.

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

const Dashboard = () => {
  const user = { name: 'John Doe', role: 'Admin' }; // Example user data

  return (
    <div>
      <h2>Dashboard</h2>
      <nav>
        <ul>
          <li>
            <Link to="">Profile</Link>
          </li>
          <li>
            <Link to="settings">Settings</Link>
          </li>
        </ul>
      </nav>
      <hr />
      <Outlet context={{ user }} />
    </div>
  );
};

export default Dashboard;

Enter fullscreen mode Exit fullscreen mode

Profile Component

The Profile component retrieves context data using useOutletContext.

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

const Profile = () => {
  const { user } = useOutletContext();

  return (
    <div>
      <h3>Profile</h3>
      <p>Name: {user.name}</p>
      <p>Role: {user.role}</p>
    </div>
  );
};

export default Profile;

Enter fullscreen mode Exit fullscreen mode

Settings Component

The Settings component also uses useOutletContext to access user data.

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

const Settings = () => {
  const { user } = useOutletContext();

  return (
    <div>
      <h3>Settings</h3>
      <p>Adjust your settings here, {user.name}.</p>
    </div>
  );
};

export default Settings;

Enter fullscreen mode Exit fullscreen mode

Conclusion

React Router v6 provides an effective approach in React applications for complex routing systems. Through usage of nested routes, index routes, NavLink, and Outlet, this allows creation of the organized and changeable navigation system. By following this guide step by step, developers will be able to lay out a foundation for making advanced React applications.

đź’– đź’Ş đź™… đźš©
vikram-boominathan
Vikraman

Posted on May 24, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related