【Next.js】コンポーネントの種類と使い分けをコード例で解説

公開日: 2026年9月7日 · 読了目安 10 分

Next.js のコンポーネントの基礎を解説します。サーバーコンポーネントとクライアントコンポーネントの違い、page.tsx や layout.tsx などファイル名の役割、props と children の書き方をコード例つきで紹介します。

Next.js のコンポーネントとは

コンポーネントは、表示を部品に分けた関数です。ヘッダーやボタンのように、同じ見た目を何度も使い回せます。この記事では、Next.js(App Router)のコンポーネントの種類と使い分けを、コード例つきで解説します。

先に要点をまとめると、次の2つです。

1つ目は、コンポーネントはデフォルトのまま書き、useState や onClick が必要な時だけ先頭に "use client" と書くこと。

2つ目は、app フォルダではファイル名が役割を決めること。page.tsx は画面、layout.tsx は共通の枠、loading.tsx は読み込み中の画面、error.tsx はエラー画面を担当します。

props と children の使い方

基本の使い方は props と children の2つです。順に見ます。

props:ページごとに変わる値を渡す

ヘッダーを例にします。タイトルはページごとに変わるので、props で受け取ります。props は読み取り専用で、受け取った側で書き換えることはできません。

components/SiteHeader.tsx
type SiteHeaderProps = { title: string };

export function SiteHeader({ title }: SiteHeaderProps) {
  return (
    <header className="border-b px-4 py-3">
      <h1 className="text-lg font-bold">{title}</h1>
    </header>
  );
}

// 使う側
<SiteHeader title="DesignLayer" />

children:タグの中身をそのまま受け取る

カードのように、枠は共通で中身だけ変えたい部品には children を使います。タグの間に書いた要素が、そのまま children として渡されます。

components/Card.tsx
import type { ReactNode } from "react";

export function Card({ children }: { children: ReactNode }) {
  return (
    <div className="rounded-lg border p-4 shadow-sm">
      {children}
    </div>
  );
}

// 使う側:中身は自由
<Card>
  <h2>料金プラン</h2>
  <p>月額2,980円</p>
</Card>

サーバーコンポーネントとクライアントコンポーネントの違い

App Router では、何も指定しなければサーバーコンポーネントとして動きます。サーバー側で実行されるため、データ取得を直接書けて、ブラウザに送る JavaScript を減らせます。

次のどれかを使いたい場合は、ファイルの先頭に "use client" と書きます。useState や useEffect などのフック、onClick などのイベント、window や localStorage などのブラウザ API です。どれも使わなければ、何も書かなくて大丈夫です。

クライアントコンポーネントの例

components/Counter.tsx
"use client"; // これが必須

import { useState } from "react";

export function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  );
}

"use client" を忘れるとエラーになる

"use client" を書かずに useState を使うと、ビルド時にエラーになります。このエラーが出たら、そのファイルに "use client" が必要かどうかを確認してください。

アニメーションライブラリ(Framer Motion など)や、ホバーで動く UI もクライアントコンポーネントが必要です。

サーバーとクライアントを組み合わせる時のルール

クライアントコンポーネントの中に置いた部品は、すべてクライアントコンポーネントとして扱われます。

サーバーコンポーネントからクライアントコンポーネントを読み込むことはできますが、逆はできません。

そのため、ページはサーバーコンポーネントのままにして、動きのある部品だけをクライアントコンポーネントにする分け方が一般的です。

app フォルダのファイル名と役割(page / layout / loading / error)

app フォルダでは、決められたファイル名に役割が割り当てられています。よく使うものを順に見ます。

page.tsx:その URL の画面

URL に対応する画面を書くファイルです。

app/page.tsx
export default function Home() {
  return <h1>Home Page</h1>;
}

layout.tsx:ページをまたいで残る枠

ヘッダーやサイドバーなど、配下のページで共有する部分を書きます。ページ遷移しても状態(スクロール位置など)が維持されます。

app/layout.tsx
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <div>
      <header>Header</header>
      <main>{children}</main>
      <footer>Footer</footer>
    </div>
  );
}

loading.tsx:読み込み中に自動で出る画面

同じフォルダに置くだけで、データ取得中に自動表示されます。スケルトンスクリーンを置く場所はここです。

app/loading.tsx
export default function Loading() {
  return <p>Loading...</p>;
}

error.tsx:エラー時の画面("use client" 必須)

app/error.tsx
"use client";

export default function Error({ error, reset }: { error: Error; reset: () => void }) {
  return (
    <div>
      <h2>エラーが発生しました</h2>
      <p>{error.message}</p>
      <button onClick={() => reset()}>再試行</button>
    </div>
  );
}

template.tsx・not-found.tsx・middleware.ts

template.tsx — layout に似ていますが、遷移のたびに再マウントされます。入場アニメーションを毎回再生したい時に使います。

not-found.tsx — 404 画面をカスタマイズします。

middleware.ts — コンポーネントではありませんが、リクエスト時に認証チェックやリダイレクトを挟む仕組みです。

コンポーネント設計の基本:1ファイル1役割に分ける

1つのコンポーネントに「データ取得・表示・ボタンの処理」を全部まとめると、あとから直しにくくなります。

分け方は、データ取得はサーバーコンポーネント(page.tsx など)、表示は props を受け取るだけの部品、操作はクライアントコンポーネント、という3つです。役割ごとに分けると、直したい場所をすぐに見つけられます。

app/posts/page.tsx
// サーバーコンポーネント:取得だけ担当
async function PostsPage() {
  const posts = await fetchPosts();
  return <PostList posts={posts} />;
}

// 表示だけ担当する部品(props を受け取るだけ)
function PostList({ posts }: { posts: Post[] }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

汎用コンポーネントは自作せずコピーして使う

ここまでの内容で自作できます。ただ、ボタンやフォームのような汎用的な部品を毎回ゼロから書く必要はありません。

よく使われているのが shadcn/ui です。ライブラリとして追加するのではなく、コンポーネントのソースを自分のリポジトリにコピーする方式なので、あとから自由に改造できます。追加は次のコマンドです。

bash
npx shadcn@latest add button

アニメーション付きセクションはコピーして使う

入場アニメーションやスクロール連動のセクションは、自分で書くと1ブロックに半日かかることもあります。こういう部品は、カタログからコピーして使うのが早いです。

DesignLayer では、アニメーション付きの React セクションをブラウザ上で動かして確認し、TSX + Tailwind のソースをそのままコピーできます。"use client" や必要なパッケージの一覧も含まれているので、そのまま貼って動かせます。

コピーしたあとは Cursor や Claude に貼り、「既存の色や余白に合わせて」と指示すると、文言や色の差し替えもまとめてできます。

まとめ:Next.js コンポーネントの使い分け

・コンポーネントはデフォルト(サーバー)で書き、状態やイベントが必要な時だけ "use client" を書く

・app フォルダではファイル名が役割を持つ。page / layout / loading / error を使い分ける

・値の受け渡しは props、中身を包む部品は children で作る

・汎用部品は shadcn/ui、アニメーション付きセクションは DesignLayer のカタログからコピーすると早い

DesignLayer のコンポーネントカタログは、閲覧無料・カード不要です。ライブプレビューで動きを確認し、無料枠(1日1回)で1セクションを自分のプロジェクトに貼ってみてください。無制限コピーと完成1ページの Templates は Pro(月額2,980円・税込)で利用できます。

【Next.js】コンポーネントの種類と使い分けをコード例で解説 | DesignLayer