Next.js

Lesson 04

Small client component islands

Place client-only behavior in the smallest component that needs it.

Good Code

app/layout.tsx
import { SearchBox } from "./search-box";
import { SiteLogo } from "./site-logo";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  // Only SearchBox needs client JavaScript; the root layout stays server-rendered.
  return (
    <html lang="en">
      <body>
        <header>
          <SiteLogo />
          <SearchBox />
        </header>
        {children}
      </body>
    </html>
  );
}

Bad Code

app/layout.tsx
"use client";

import { useState } from "react";
import { SiteLogo } from "./site-logo";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const [query, setQuery] = useState("");

  // One input state pulls the whole root layout into the client bundle.
  return (
    <html lang="en">
      <body>
        <header>
          <SiteLogo />
          <input value={query} onChange={(event) => setQuery(event.target.value)} />
        </header>
        {children}
      </body>
    </html>
  );
}

Review Notes

What to review

Good Code

The good version keeps the root layout server-rendered and imports a small Client Component for the search interaction.

Bad Code

The bad version marks the root layout as a Client Component just to hold input state, making static shell and imported children part of the client graph.

Takeaways

  • A tiny client island keeps static UI and server data out of the browser bundle.