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

これまで、アプリケーションにはホームページしかありませんでした。レイアウトページを使用して、さらに多くのルートを作成する方法を学びましょう。

ネストされたルーティング

Next.js では、フォルダを使用してネストされたルートを作成するファイルシステムベースのルーティングが採用されています。各フォルダは、URLセグメントに対応するルートセグメントを表します。

フォルダがURLセグメントにマッピングされる様子を示す図

各ルート用に個別のUIを作成するには、layout.tsxpage.tsx ファイルを使用します。

page.tsx はReactコンポーネントをエクスポートする特別なNext.jsファイルで、ルートがアクセス可能になるために必要です。アプリケーションには既にページファイルがあります: /app/page.tsx - これはルート / に関連付けられたホームページです。

ネストされたルートを作成するには、フォルダを互いに入れ子にし、その中に page.tsx ファイルを追加します。例えば:

dashboardというフォルダを追加することで新しいルート '/dashboard' が作成される様子を示す図

/app/dashboard/page.tsx/dashboard パスに関連付けられます。実際にページを作成して動作を確認してみましょう!

ダッシュボードページの作成

/app 内に dashboard という新しいフォルダを作成します。次に、dashboard フォルダ内に新しい page.tsx ファイルを作成し、以下の内容を記述します:

/app/dashboard/page.tsx
export default function Page() {
  return <p>ダッシュボードページ</p>;
}

開発サーバーが実行されていることを確認し、http://localhost:3000/dashboard にアクセスしてください。「ダッシュボードページ」というテキストが表示されるはずです。

これがNext.jsで異なるページを作成する方法です: フォルダを使用して新しいルートセグメントを作成し、その中に page ファイルを追加します。

page ファイルに特別な名前を付けることで、Next.jsではUIコンポーネント、テストファイル、その他の関連コードをルートと同位置に配置できます。page ファイル内のコンテンツのみが公開的にアクセス可能になります。例えば、/ui/lib フォルダは、ルートと共に /app フォルダ内に同位置配置されています。

練習: ダッシュボードページの作成

さらに多くのルートを作成する練習をしましょう。ダッシュボード内に2つのページを作成します:

  1. 顧客ページ: http://localhost:3000/dashboard/customers でアクセス可能。現時点では <p>顧客ページ</p> 要素を返すようにします。
  2. 請求書ページ: http://localhost:3000/dashboard/invoices でアクセス可能。現時点では <p>請求書ページ</p> 要素を返すようにします。

この演習に取り組んでみてください。準備ができたら、以下のトグルを展開して解答を確認してください:

ダッシュボードレイアウトの作成

ダッシュボードには、複数のページ間で共有されるナビゲーションがあります。Next.jsでは、特別な layout.tsx ファイルを使用して、複数のページ間で共有されるUIを作成できます。ダッシュボードページ用のレイアウトを作成しましょう!

/dashboard フォルダ内に layout.tsx という新しいファイルを追加し、以下のコードを貼り付けます:

/app/dashboard/layout.tsx
import SideNav from '@/app/ui/dashboard/sidenav';
 
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
      <div className="w-full flex-none md:w-64">
        <SideNav />
      </div>
      <div className="flex-grow p-6 md:overflow-y-auto md:p-12">{children}</div>
    </div>
  );
}

このコードではいくつかのことが行われているので、分解してみましょう:

まず、<SideNav /> コンポーネントをレイアウトにインポートしています。このファイルにインポートするコンポーネントはすべてレイアウトの一部になります。

<Layout /> コンポーネントは children プロップを受け取ります。この子要素はページまたは別のレイアウトのいずれかです。この場合、/dashboard 内のページは自動的に <Layout /> 内にネストされます:

ダッシュボードレイアウトがダッシュボードページを子としてネストするフォルダ構造

変更を保存し、localhostを確認してすべてが正しく動作していることを確認してください。次のように表示されるはずです:

サイドナビとメインコンテンツ領域を持つダッシュボードページ

Next.jsでレイアウトを使用する利点の1つは、ナビゲーション時にページコンポーネントのみが更新され、レイアウトは再レンダリングされないことです。これは部分レンダリングと呼ばれ、ページ間を移動する際にレイアウト内のクライアントサイドReactの状態を保持します。

ダッシュボードレイアウトがダッシュボードページをネストするフォルダ構造を示す図。ナビゲーション時にはページUIのみが入れ替わる

ルートレイアウト

第3章では、Inter フォントを別のレイアウト /app/layout.tsx にインポートしました。念のため:

/app/layout.tsx
import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts';
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={`${inter.className} antialiased`}>{children}</body>
    </html>
  );
}

これはルートレイアウトと呼ばれ、すべてのNext.jsアプリケーションで必須です。ルートレイアウトに追加したUIは、アプリケーションのすべてのページで共有されます。ルートレイアウトを使用して <html><body> タグを変更したり、メタデータを追加できます(メタデータについては後の章で詳しく学びます)。

今作成した新しいレイアウト (/app/dashboard/layout.tsx) はダッシュボードページに固有のものなので、上記のルートレイアウトにUIを追加する必要はありません。

On this page