Next.js Learn Course をやってみる Chapter4
レイアウトとページの作成
💡 ここがApp Routerで変わった事が一番よくわかるかなーと思い、先にやりましたが、後から見てみるとChapter3の内容を記述しないとコンパイルエラーになるので、順番にやってください。
このチャプターでやること
- ファイルシステムのルーティングを使って、/login, dashboardのページを作成
- 新しいルートを作るときのフォルダとファイルの役割の理解
- 複数のダッシュボードページの間で共有されるレイアウトの作成
- colocation, partial rendering, root layoutの理解
ネストされたルーティング
Next.jsではフォルダに置かれたファイルの構造がそのままWebページのパスと一致します。
- app
- dashboard
- invoices
- dashboard
acme.com / dashboard /invoices
以前まではpagesフォルダでしたが、app routerだとルートはappフォルダになるみたいですね。
page.tsxはルートのためのUIを含んだReactコンポーネントexportする特別なNext.jsのファイルになります。
/app/page.tsxはドメイン直下のホームページを表示するファイルになります。
フォルダのネストがそのままURLと一致するので、ログインページ (あなたのドメイン/login)を作る場合は、/app/login/page.tsx を作成します。
ダッシュボードのページを作る
app / dashboard / page.tsxを作成し、以下のコードを書く。
export default function Page() {
return <p>Dashboard Page</p>;
}
これで http://localhost:3000/dashboard に行くと上で書かれたテキストが表示されています。
特別な page ファイルを持つことによって、同じディレクトリにUIコンポーネントやテストファイルを置くことができます。pageファイル内のコンテントのみ公開されます。とても便利。
レイアウトを作る
複数のページにまたがるレイアウトを作成します。例えば、上部にあるタブメニューなどはどのページにも出して欲しいですよね。
特別なファイルとして layout.tsx を使用します。
/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>
);
}
Layoutコンポーネントは、 children propを受け取り、/dashboard配下にある全てのページは自動的にchildrenとして内部にネストされます。
Webサイトで共通で使いたいヘッダーやサイドメニューなどはLayout.tsxに書いておけば、全てのPageに適用されます。(上の例だとdashboardフォルダと並列に置いた場合は適用されないので、フォルダを確認)
レイアウトの利点は、ナビゲーション時に、ページコンポーネントだけが更新され、レイアウトは再レンダリングされないこと!(めっちゃ便利だけど、例えばサイドメニューに今いるページの場所を表示したいとかなるとどうなるんだろう)
これをPartial Renderingと呼びます。
Root Layout
/app/layout.tsx はルートレイアウトと呼びます。これは必須で、ここに追加したUIはアプリケーションの全てのページで共有されます。
ルートレイアウトを使って <html><body>タグを修正し、メタデータを追加できます。
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}`}>{children}</body>
</html>
);
}
削除すると怒られます。
Discussion