Menu

レイアウトとページの作成方法

Next.jsはファイルシステムベースのルーティングを使用しており、フォルダとファイルを使用してルートを定義します。このページでは、レイアウトとページを作成し、それらをリンクする方法について説明します。

ページの作成

ページは特定のルートにレンダリングされるUIです。ページを作成するには、appディレクトリ内にpageファイルを追加し、Reactコンポーネントをデフォルトエクスポートします。たとえば、インデックスページ(/)を作成するには:

page.js 特殊ファイル
app/page.tsx
TypeScript
export default function Page() {
  return <h1>Hello Next.js!</h1>
}

レイアウトの作成

レイアウトは複数のページ間で共有されるUIです。ナビゲーション時、レイアウトは状態を保持し、インタラクティブなままであり、再レンダリングされません。

レイアウトを定義するには、layoutファイルからReactコンポーネントをデフォルトエクスポートします。コンポーネントは、ページまたは別のレイアウトを含むchildrenプロップを受け取る必要があります。

たとえば、インデックスページを子として受け取るレイアウトを作成するには、appディレクトリ内にlayoutファイルを追加します:

layout.js 特殊ファイル
app/layout.tsx
TypeScript
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        {/* Layout UI */}
        {/* Place children where you want to render a page or nested layout */}
        <main>{children}</main>
      </body>
    </html>
  )
}

上記のレイアウトはルートレイアウトと呼ばれ、appディレクトリのルートに定義されています。ルートレイアウトは必須であり、htmlbodyタグを含む必要があります。

ネストされたルートの作成

ネストされたルートは、複数のURLセグメントで構成されるルートです。たとえば、/blog/[slug]ルートは3つのセグメントで構成されています:

  • /(ルートセグメント)
  • blog(セグメント)
  • [slug](リーフセグメント)

Next.jsでは:

  • フォルダはURLセグメントにマッピングするルートセグメントを定義するために使用されます。
  • ファイルpagelayoutなど)はセグメントに表示されるUIを作成するために使用されます。

ネストされたルートを作成するには、フォルダを互いにネストすることができます。たとえば、/blogのルートを追加するには、appディレクトリ内にblogという名前のフォルダを作成します。次に、/blogを公開してアクセス可能にするには、pageファイルを追加します:

blogフォルダとpage.jsファイルを示すファイル階層
app/blog/page.tsx
TypeScript
import { getPosts } from '@/lib/posts'
import { Post } from '@/ui/post'
 
export default async function Page() {
  const posts = await getPosts()
 
  return (
    <ul>
      {posts.map((post) => (
        <Post key={post.id} post={post} />
      ))}
    </ul>
  )
}

ネストされたルートを作成するために、フォルダのネストを続けることができます。たとえば、特定のブログ投稿のルートを作成するには、blog内に新しい[slug]フォルダを作成し、pageファイルを追加します:

ネストされたslugフォルダとpage.jsファイルを持つblogフォルダを示すファイル階層
app/blog/[slug]/page.tsx
TypeScript
function generateStaticParams() {}
 
export default function Page() {
  return <h1>Hello, Blog Post Page!</h1>
}

補足: フォルダ名を角括弧で囲む(例:[slug])と、データから複数のページを生成するための特別な動的ルートセグメントが作成されます。これはブログ記事、商品ページなどに便利です。

レイアウトのネスト

デフォルトでは、フォルダ階層内のレイアウトもネストされ、childrenプロップを通じて子レイアウトをラップします。特定のルートセグメント(フォルダ)内にlayoutを追加することで、レイアウトをネストできます。

たとえば、/blogルート用のレイアウトを作成するには、blogフォルダ内に新しいlayoutファイルを追加します。

ルートレイアウトがブログレイアウトをラップしていることを示すファイル階層
app/blog/layout.tsx
TypeScript
export default function BlogLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return <section>{children}</section>
}

上記の2つのレイアウトを組み合わせると、ルートレイアウト(app/layout.js)はブログレイアウト(app/blog/layout.js)をラップし、さらにブログページ(app/blog/page.js)とブログ投稿ページ(app/blog/[slug]/page.js)をラップします。

ページ間のリンク

<Link> コンポーネントを使用して、ルート間を移動できます。<Link>はNext.jsの組み込みコンポーネントで、HTML <a>タグを拡張してプリフェッチとクライアントサイドナビゲーションを提供します。

たとえば、ブログ投稿のリストを生成するには、next/linkから<Link>をインポートし、コンポーネントにhrefプロップを渡します:

app/ui/post.tsx
TypeScript
import Link from 'next/link'
 
export default async function Post({ post }) {
  const posts = await getPosts()
 
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.slug}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  )
}

<Link>はNext.jsアプリケーションでルート間を移動するための主要かつ推奨される方法です。ただし、より高度なナビゲーションにはuseRouterフックも使用できます。