Next.jsページコンポーネントの作成

2025-08-12

はじめに

前回の記事ではNext.jsの特徴とファイルルーティングについて学びました。今回は、実際にページコンポーネントを作成する方法について詳しく解説します。Reactの知識がある方なら、Next.jsのページコンポーネントはとても理解しやすいでしょう。

ページコンポーネントとは?

Next.jsでは、pagesディレクトリ内の各ファイルが自動的に1つのページ(ルート)として認識されます。これらのファイルでエクスポートされたReactコンポーネントが「ページコンポーネント」です。

基本的な特徴

  • 各ページは独立したReactコンポーネント
  • ファイルの場所がURLパスを決定
  • 特別なライフサイクルやプロパティを持つ
  • 自動的なコード分割が行われる

基本的なページコンポーネントの作成

1. 静的ページの作成

最もシンプルなページコンポーネントは、Reactの関数コンポーネントと同じ形式で作成できます。

pages/about.jsを作成してみましょう:

// ページコンポーネントは通常のReactコンポーネントと同じように作成
function AboutPage() {
  return (
    <div>
      <h1>About Us</h1>
      <p>私たちについての情報を掲載しています</p>
    </div>
  );
}

// コンポーネントをデフォルトエクスポートする必要がある
export default AboutPage;

このコードは、/aboutにアクセスした時に表示されるページを作成します。

2. ページコンポーネントの構造

典型的なページコンポーネントの構造は以下のようになります:

// 1. 必要なライブラリやコンポーネントをインポート
import Head from 'next/head';
import Layout from '../components/Layout';

// 2. ページコンポーネントを定義
function HomePage() {
  // 3. コンポーネントのロジック(状態管理など)
  const [count, setCount] = useState(0);

  // 4. JSXでUIを記述
  return (
    <Layout>
      <Head>
        <title>ホームページ</title>
        <meta name="description" content="ウェルカムページです" />
      </Head>
      <h1>Welcome to Next.js!</h1>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </Layout>
  );
}

// 5. コンポーネントをデフォルトエクスポート
export default HomePage;

ページコンポーネントの種類

Next.jsにはいくつかの特別なページコンポーネントがあります:

1. インデックスページ (index.js)

アプリケーションのルート(/)に対応するページ:

// pages/index.js
export default function Home() {
  return <h1>Welcome to our website!</h1>;
}

2. ネストされたページ

ディレクトリ構造を反映したページ:

pages/
└── products/
    ├── index.js      # /products
    └── detail.js    # /products/detail

3. 動的ルートページ

角括弧を使った動的なページ:

pages/
└── blog/
    └── [slug].js    # /blog/hello-world, /blog/nextjs-is-great など

ページコンポーネントの特殊プロパティ

Next.jsのページコンポーネントは、いくつかの特別なプロパティや関数をサポートしています。

1. getStaticProps (SSG用)

ビルド時にデータを取得する関数:

export async function getStaticProps() {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  return {
    props: {
      data
    }
  };
}

function Page({ data }) {
  // データを使用してページをレンダリング
}

2. getServerSideProps (SSR用)

リクエストごとにデータを取得する関数:

export async function getServerSideProps(context) {
  const { params, req, res } = context;

  const user = await getUser(req);

  return {
    props: {
      user
    }
  };
}

3. getStaticPaths (動的SSG用)

動的ルートでどのパスをプリレンダリングするか指定:

export async function getStaticPaths() {
  return {
    paths: [
      { params: { id: '1' } },
      { params: { id: '2' } }
    ],
    fallback: false
  };
}

ページコンポーネント作成のベストプラクティス

1. ページごとにフォルダを分ける

関連するコンポーネントやスタイルを同じディレクトリにまとめます:

pages/
└── blog/
    ├── [slug].js
    ├── components/    # このページ専用のコンポーネント
    └── styles/        # このページ専用のスタイル

2. レイアウトコンポーネントを使用

共通のレイアウトを適用:

// components/Layout.js
export default function Layout({ children }) {
  return (
    <div className="layout">
      <Header />
      <main>{children}</main>
      <Footer />
    </div>
  );
}

// pages/about.js
import Layout from '../components/Layout';

export default function About() {
  return (
    <Layout>
      <h1>About Page</h1>
    </Layout>
  );
}

3. メタデータを管理

next/headを使用してページごとにメタデータを設定:

import Head from 'next/head';

export default function ProductPage() {
  return (
    <>
      <Head>
        <title>製品情報 | 会社名</title>
        <meta name="description" content="当社製品の詳細情報ページです" />
      </Head>
      {/* ページコンテンツ */}
    </>
  );
}

実際のページコンポーネント作成例

ブログ記事ページの例

pages/blog/[slug].js:

import { useRouter } from 'next/router';
import Layout from '../../components/Layout';
import Head from 'next/head';

export async function getStaticProps({ params }) {
  // 実際のアプリではAPIやデータベースからデータを取得
  const postData = {
    title: `記事: ${params.slug}`,
    content: 'これはサンプルの記事内容です...',
    date: '2023-05-01'
  };

  return {
    props: {
      postData
    }
  };
}

export async function getStaticPaths() {
  // 実際のアプリでは全てのスラグを取得
  const paths = [
    { params: { slug: 'first-post' } },
    { params: { slug: 'second-post' } }
  ];

  return {
    paths,
    fallback: false
  };
}

export default function BlogPost({ postData }) {
  const router = useRouter();
  const { slug } = router.query;

  return (
    <Layout>
      <Head>
        <title>{postData.title}</title>
      </Head>
      <article>
        <h1>{postData.title}</h1>
        <p>{postData.date}</p>
        <div>{postData.content}</div>
      </article>
    </Layout>
  );
}

よくある間違いと解決方法

1. デフォルトエクスポートを忘れる

間違い:

export function HomePage() { ... }

正しい方法:

export default function HomePage() { ... }

2. コンポーネント名とファイル名の不一致

ファイル名とコンポーネント名は一致させなくても動作しますが、保守性のために一致させるのがベストプラクティスです。

3. 状態管理の誤った使用

ページコンポーネントでもuseStateは使用できますが、SSR/SSGとの整合性に注意が必要です。

まとめ

Next.jsのページコンポーネント作成は、Reactの知識があればすぐに習得できます。主なポイントは:

  1. pagesディレクトリ内にファイルを作成するだけで自動的にルーティングが設定される
  2. 通常のReactコンポーネントと同じように作成できるが、デフォルトエクスポートが必要
  3. 特別な関数(getStaticPropsなど)を使用してデータ取得を最適化できる
  4. レイアウトコンポーネントやHeadコンポーネントでページを拡張できる

次のステップでは、作成したページ間をリンクで接続する方法を学びます。Next.jsのLinkコンポーネントを使用すると、クライアントサイドナビゲーションを簡単に実装でき、ページ遷移が高速化されます。

Next.jsの公式ドキュメントも参考にしてください:
https://nextjs.org/docs/basic-features/pages