コンテンツへスキップ
App Routerはじめにレイアウトとページ

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

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

ページの作成

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

page.js special file
app/page.tsx
export default function Page() {
  return <h1>Hello Next.js!</h1>
}

レイアウトの作成

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

レイアウトは、layoutファイルからReactコンポーネントをデフォルトエクスポートすることで定義できます。このコンポーネントは、ページまたは別のレイアウトになり得るchildrenプロパティを受け入れる必要があります。

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

layout.js special file
app/layout.tsx
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ディレクトリのルートに定義されているため、ルートレイアウトと呼ばれます。ルートレイアウトは必須であり、htmlおよびbodyタグを含める必要があります。

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

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

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

Next.jsでは

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

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

File hierarchy showing blog folder and a page.js file
app/blog/page.tsx
// Dummy imports
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ファイルを追加します。

File hierarchy showing blog folder with a nested slug folder and a page.js file
app/blog/[slug]/page.tsx
function generateStaticParams() {}
 
export default function Page() {
  return <h1>Hello, Blog Post Page!</h1>
}

フォルダー名を角括弧 (例: [slug]) で囲むと、動的ルートセグメントが作成され、これを使用してデータから複数のページ (例: ブログ投稿、製品ページなど) を生成します。

レイアウトのネスト

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

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

File hierarchy showing root layout wrapping the blog layout
app/blog/layout.tsx
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>は、HTML <a>タグを拡張してプリフェッチクライアントサイドナビゲーションを提供する、Next.jsに組み込まれたコンポーネントです。

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

app/ui/post.tsx
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フックを使用することもできます。