Next.js: A Practical Introduction for Developers

Nested Routes and Layouts

Section 4

Pages and Routing: Navigating Your Application

Next.js: A Practical Introduction for DevelopersPages and Routing: Navigating Your Application

As your application grows, you'll often find yourself needing to group related pages under a common structure or theme. This is where nested routes and layouts in Next.js shine. They allow you to define shared UI elements, like navigation bars, footers, or sidebars, that persist across a set of related pages, enhancing user experience and simplifying your codebase.

Next.js's file-system based routing makes implementing nested routes intuitive. You can create directories within your pages directory to represent nested URL segments. For example, a route like /dashboard/settings can be achieved by creating pages/dashboard/settings.js.

import { useRouter } from 'next/router';

function SettingsPage() {
  const router = useRouter();
  const { slug } = router.query; // If you had dynamic segments like /dashboard/settings/[slug].js

  return (
    <div>
      <h1>Dashboard Settings</h1>
      <p>This is the settings page for the dashboard.</p>
    </div>
  );
}

export default SettingsPage;

Beyond just nesting, the real power comes with defining shared layouts for these nested routes. Next.js provides a flexible way to achieve this using a pattern that leverages component composition.

The common approach is to create a layout component that accepts children and wraps them with shared elements. Then, within your page components that belong to a specific nested route, you'll import and use this layout component.

/* components/DashboardLayout.js */
import Navbar from './Navbar';
import Sidebar from './Sidebar';

export default function DashboardLayout({ children }) {
  return (
    <div className="dashboard-container">
      <Navbar />
      <div className="main-content">
        <Sidebar />
        <main>{children}</main>
      </div>
      <style jsx>{`
        .dashboard-container {
          display: flex;
          flex-direction: column;
          min-height: 100vh;
        }
        .main-content {
          display: flex;
          flex: 1;
        }
        main {
          flex: 1;
          padding: 20px;
        }
      `}</style>
    </div>
  );
}
/* pages/dashboard/index.js */
import DashboardLayout from '../../components/DashboardLayout';

function DashboardPage() {
  return (
    <div>
      <h2>Welcome to your Dashboard!</h2>
      <p>This is the main dashboard overview.</p>
    </div>
  );
}

DashboardPage.getLayout = function getLayout(page) {
  return (
    <DashboardLayout>
      {page}
    </DashboardLayout>
  );
};

export default DashboardPage;
/* pages/dashboard/settings.js */
import DashboardLayout from '../../components/DashboardLayout';

function SettingsPage() {
  return (
    <div>
      <h2>Dashboard Settings</h2>
      <p>Adjust your settings here.</p>
    </div>
  );
}

SettingsPage.getLayout = function getLayout(page) {
  return (
    <DashboardLayout>
      {page}
    </DashboardLayout>
  );
};

export default SettingsPage;
チャプターへ戻る