Skip to content

Next.js Components and Layout

In React and Next.js, components are the core of building user interfaces. By breaking UI into independent, reusable parts, we can more efficiently develop and maintain complex applications. This chapter explores how to organize components in Next.js and create shared layouts for multiple pages.

1. Component Basics

In Next.js, components are written exactly the same way as in standard React projects. Typically, we store all components in a components folder in the project root directory for easy management.

Creating a Simple Component

Let's create a simple Button component.

  1. Create file: components/Button.js

  2. Write component code:

    jsx
    // components/Button.js
    import styles from './Button.module.css';
    
    export default function Button({ children, onClick }) {
      return (
        <button className={styles.button} onClick={onClick}>
          {children}
        </button>
      );
    }
  3. Add styles for the component (optional): components/Button.module.css

    css
    .button {
      background-color: #0070f3;
      color: white;
      padding: 10px 20px;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      font-size: 1rem;
    }
    
    .button:hover {
      background-color: #005bb5;
    }

Using Components in Pages

Now you can import and use this Button component in any page.

jsx
// pages/index.js
import Button from '../components/Button';

export default function HomePage() {
  const handleClick = () => {
    alert('Button clicked!');
  };

  return (
    <div>
      <h1>Welcome to My App</h1>
      <Button onClick={handleClick}>Click Me</Button>
    </div>
  );
}

2. Page Layouts

In most websites, multiple pages share the same structure, such as header, footer, and navigation bar. In Next.js, there are several ways to implement this shared layout.

Method 1: Create a Layout Component

The most common approach is to create a Layout component and use it to wrap each page's content.

  1. Create Layout component: components/Layout.js

    This component typically contains the header, footer, and renders page content through the children prop.

    jsx
    // components/Layout.js
    import Head from 'next/head';
    import Header from './Header';
    import Footer from './Footer';
    
    export default function Layout({ children, title = 'My Next.js App' }) {
      return (
        <div>
          <Head>
            <title>{title}</title>
            <meta charSet="utf-8" />
            <meta name="viewport" content="initial-scale=1.0, width=device-width" />
          </Head>
    
          <Header />
    
          <main>{children}</main>
    
          <Footer />
        </div>
      );
    }

    We also need to create Header and Footer components.

    components/Header.js

    jsx
    import Link from 'next/link';
    import styles from './Header.module.css';
    
    export default function Header() {
      return (
        <header className={styles.header}>
          <nav>
            <Link href="/">Home</Link>
            <Link href="/about">About</Link>
            <Link href="/contact">Contact</Link>
          </nav>
        </header>
      );
    }

    components/Footer.js

    jsx
    import styles from './Footer.module.css';
    
    export default function Footer() {
      return (
        <footer className={styles.footer}>
          <p>© {new Date().getFullYear()} My Awesome App. All rights reserved.</p>
        </footer>
      );
    }
  2. Use Layout component in _app.js

    To have all pages use this layout, we can wrap Component in pages/_app.js.

    jsx
    // pages/_app.js
    import Layout from '../components/Layout';
    import '../styles/globals.css';
    
    function MyApp({ Component, pageProps }) {
      return (
        <Layout>
          <Component {...pageProps} />
        </Layout>
      );
    }
    
    export default MyApp;

    This way, the Layout component will automatically apply to all pages without needing to import it separately in each page file.

Method 2: Per-Page Layouts

Sometimes, your application may need multiple different layouts (e.g., one for the main app, one for the admin dashboard). In this case, you can add a getLayout property to page components.

  1. Modify _app.js

    First, modify _app.js to support the getLayout function.

    jsx
    // pages/_app.js
    import '../styles/globals.css';
    
    export default function MyApp({ Component, pageProps }) {
      // Use getLayout if the page has one
      const getLayout = Component.getLayout || ((page) => page);
    
      return getLayout(<Component {...pageProps} />);
    }
  2. Specify layout in pages

    Now you can define getLayout in pages that need a specific layout.

    jsx
    // pages/dashboard.js
    import AdminLayout from '../components/AdminLayout';
    
    export default function DashboardPage() {
      return (
        <div>
          <h1>Admin Dashboard</h1>
          {/* ... */}
        </div>
      );
    }
    
    // Define the layout for this page
    DashboardPage.getLayout = function getLayout(page) {
      return <AdminLayout>{page}</AdminLayout>;
    };

    Pages that don't need a special layout will default to no layout, or you can provide a default layout.

3. Layouts in App Router (Next.js 13+)

In the App Router introduced in Next.js 13, layout management becomes more native and powerful.

  • layout.js file: You can create a layout.js file in any route segment to define shared UI. This layout applies to that route segment and all its child routes.

Example: app/dashboard/layout.js

jsx
// app/dashboard/layout.js
export default function DashboardLayout({ children }) {
  return (
    <section>
      {/* Shared dashboard navigation */}
      <nav>Dashboard Nav</nav>
      {children}
    </section>
  );
}

This layout will automatically wrap app/dashboard/page.js and all child pages like app/dashboard/settings/page.js.

Summary

  • Components are the basic units for building UI and should be kept independent and reusable.
  • Shared layouts can be implemented by creating a Layout component and using it in _app.js.
  • For complex applications requiring multiple layouts, the per-page layout pattern provides greater flexibility.
  • In the App Router, layouts are managed in a more structured way through layout.js files.

In the final chapter, we'll provide some useful learning resources to help you continue your in-depth study of Next.js.

Content is for learning and research only.