notFound()とnot-found.tsxの関係とは?404ページの仕組みを初心者向けにやさしく解説


Next.js・microCMS 初心者ノート

notFound()とnot-found.tsxの関係とは? 404ページの仕組みを初心者向けにやさしく解説

notFound()とnot-found.tsxの関係とは?404ページの仕組みを初心者向けに解説

Next.jsで記事詳細ページを作っていると、 notFound()という関数と not-found.tsxというファイルが登場します。
名前がよく似ているため、 「どちらが404ページなの?」「両方必要なの?」と 最初は迷いやすい部分です。
今回は、microCMSの記事が存在しなかった場合を例に、 2つの役割と処理の流れを整理します。

Next.js notFound() not-found.tsx 404ページ microCMS 初心者向け
01

2つの名前が似ていて分かりにくい

Next.jsのコードを見ていると、 次のような処理が登場します。

記事がない場合の処理
if (!article) {
  notFound();
}

さらに、appフォルダー内には 次のようなファイルを作ります。

TSX
FILE NAME not-found.tsx
?

どちらが404ページなの?

notFound()もnot-found.tsxも、 名前だけを見ると404を表示するものに見えます。
しかし、2つは同じ役割ではありません。

notFound() 404表示を開始する

「このページは見つからない」と Next.jsへ伝える関数です。

not-found.tsx 404画面を作る

ユーザーに表示する 実際の画面を定義するファイルです。

notFound()は「404に切り替える処理」、
not-found.tsxは「切り替え後に表示する画面」です。

02

そもそも404ページとは?

404ページは、 ユーザーがアクセスしたURLに対応するページやデータが 見つからないときに表示するページです。

404
Page Not Found

お探しのページは見つかりませんでした。

たとえば、次のような場合に404ページが必要になります。

CASE 01 URLの入力間違い

存在しない文字列をURLへ入力した。

CASE 02 記事が削除された

以前存在した記事がmicroCMSから削除された。

CASE 03 IDが間違っている

URLの記事IDに該当するデータがない。

CASE 04 リンク先が古い

外部サイトに古いURLが残っている。

ページが存在しないのに、 空白画面やプログラムのエラーを表示すると、 ユーザーは何が起きたのか分かりません。

404ページの役割

ページが見つからないことを明確に伝え、 トップページや記事一覧など、 次に移動できる場所を案内します。

03

notFound()とは?

notFound()は、 Next.jsが提供する関数です。

ページの処理中にnotFound()を実行すると、 そのルートで通常のページ表示を中断し、 対応するnot-foundファイルのUIへ切り替えます。

()
FUNCTION ページが見つからないことをNext.jsへ伝える関数

データが存在しない場合など、 条件に応じて404表示へ切り替えます。

最初にimportする

STEP 1 notFoundを読み込む
import { notFound } from "next/navigation";

必要な条件で実行する

STEP 2 データがない場合
if (!article) {
  notFound();
}

このコードは、 articleが存在しなかった場合に notFound()を実行するという意味です。

articleがある 通常の記事を表示
articleがない notFound()を実行
returnは不要

notFound()は実行後に通常のページ処理を続けないため、 基本的にreturn notFound();と書く必要はありません。

04

not-found.tsxとは?

not-found.tsxは、 404時にユーザーへ表示するUIを作るためのファイルです。

TSX
FILE CONVENTION 404ページの見た目と内容を定義するファイル

メッセージ、リンク、イラストなどを 通常のReactコンポーネントと同じように記述します。

app/not-found.tsx
import Link from "next/link";

export default function NotFound() {
  return (
    <main>
      <p>404</p>

      <h1>
        お探しのページは見つかりませんでした
      </h1>

      <p>
        URLが変更されたか、
        ページが削除された可能性があります。
      </p>

      <Link href="/">
        トップページへ戻る
      </Link>
    </main>
  );
}

ファイル名は not-found.tsxであり、 コンポーネント名は自由に付けられます。

ファイル名 not-found.tsx
主な役割 404画面を表示
書く内容 Reactコンポーネント
05

notFound()とnot-found.tsxの関係

2つは、次の順番で連携します。

01 ページへアクセス

記事詳細URLが開かれる。

02 記事データを取得

microCMSへ記事を問い合わせる。

03 記事が存在する?

取得結果を確認する。

存在する 記事ページを表示
存在しない notFound()を実行
04 not-found.tsxを表示

ユーザーへ404画面を見せる。

notFound() きっかけ 404へ切り替える
not-found.tsx 表示内容 404画面を描画する

notFound()だけでは、404画面のデザインは作りません。
not-found.tsxだけでは、 データがない条件を自動判定できません。

06

基本的な実装方法

App Routerで記事詳細ページを作る場合は、 次のような構成になります。

app
├─ not-found.tsx
└─ blog
    └─ [id]
       └─ page.tsx

記事詳細ページ

PAGE app/blog/[id]/page.tsx
import { notFound } from "next/navigation";

type Props = {
  params: Promise<{
    id: string;
  }>;
};

export default async function BlogDetail({
  params,
}: Props) {
  const { id } = await params;

  const article = await getArticle(id);

  if (!article) {
    notFound();
  }

  return (
    <article>
      <h1>{article.title}</h1>

      <div
        dangerouslySetInnerHTML={{
          __html: article.content,
        }}
      />
    </article>
  );
}

404ページ

app/not-found.tsx
import Link from "next/link";

export default function NotFoundPage() {
  return (
    <main className="not-found-page">
      <p className="not-found-page__number">
        404
      </p>

      <h1>
        お探しのページは見つかりませんでした
      </h1>

      <p>
        ページが削除されたか、
        URLが変更された可能性があります。
      </p>

      <Link href="/blog">
        記事一覧へ戻る
      </Link>
    </main>
  );
}
07

microCMSの記事詳細ページで使う

microCMSの記事詳細ページでは、 URLの記事IDを使ってデータを取得します。

アクセスされたURL /blog/abc123
固定部分 /blog/
記事ID abc123

しかし、URLに指定されたIDの記事が microCMSに存在するとは限りません。

URL abc123
microCMS 記事を検索
結果 記事なし

取得処理で404を判定する例

microCMS 記事取得とnotFound
import { notFound } from "next/navigation";
import { client } from "@/libs/microcms";

async function getArticle(id: string) {
  try {
    return await client.get({
      endpoint: "blogs",
      contentId: id,
    });
  } catch {
    return null;
  }
}

export default async function Page({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;

  const article = await getArticle(id);

  if (!article) {
    notFound();
  }

  return (
    <article>
      <h1>{article.title}</h1>
    </article>
  );
}
判定する場所

「記事を取得できなかったら必ず404」とは限りません。 通信障害や設定ミスまで404として扱わないように、 実際の取得処理ではエラー内容を確認して設計します。

08

not-found.tsxを置く場所

not-found.tsxは、 appフォルダーのルートだけでなく、 特定のルートセグメント内にも配置できます。

サイト共通
app/not-found.tsx
全体で使う404画面
ブログ専用
app/blog/not-found.tsx
ブログ内で使う404画面
app
├─ not-found.tsx サイト共通
└─ blog
    ├─ not-found.tsx ブログ専用
    └─ [id]
       └─ page.tsx

近いルートセグメントにあるnot-foundファイルを使うことで、 ブログ用、商品用など、 コンテンツに合った案内を表示できます。

09

セグメントごとに404画面を変える

サイト全体の404と、 ブログ記事が見つからない場合では、 ユーザーに案内したい内容が異なります。

サイト共通404
ページが見つかりません

トップページへ戻る

ブログ専用404
記事が見つかりません

新着記事を見る

app/blog/not-found.tsx
import Link from "next/link";

export default function BlogNotFound() {
  return (
    <main>
      <p>404</p>

      <h1>
        お探しの記事は見つかりませんでした
      </h1>

      <p>
        記事が削除されたか、
        URLが変更された可能性があります。
      </p>

      <Link href="/blog">
        記事一覧を見る
      </Link>
    </main>
  );
}
10

存在しないURLとnotFound()の違い

404が表示される場面は、 大きく2種類に分けられます。

パターンA ルート自体が存在しない /unknown-page

app内に対応するページがなく、 Next.jsのルーターが見つけられない状態です。

パターンB ルートはあるがデータがない /blog/unknown-id

記事詳細ページはあるものの、 指定された記事が存在しない状態です。

ルートがない Next.jsが404として処理
データがない notFound()を実行
表示 not-foundのUI

Next.jsには、通常のnot-foundファイルに加え、 アプリ全体で一致しないURLを処理するための global-not-found.jsという仕組みもあります。

初心者はまず通常のnot-foundから

一般的なApp Routerのサイトでは、 まずapp/not-found.tsxとnotFound()の関係を理解すれば 基本的な404処理を組み立てられます。

11

error.tsxとの違い

404ページとエラーページは、 どちらも通常のページを表示できないときに使います。

ただし、意味は異なります。

比較項目
not-found.tsx
error.tsx
意味
ページやデータが存在しない
予期しないエラーが発生した
記事IDが見つからない
処理中に例外が発生した
呼び出し
notFound()など
未処理の例外
ユーザーへの案内
別ページへ移動してもらう
再試行などを案内する
記事が存在しない not-found.tsx

正常に確認した結果、 対象データがなかった。

処理が失敗した error.tsx

予期しない例外などで、 ページを正常表示できなかった。

すべてを404にしない

APIの接続障害やプログラムの不具合まで 「ページがありません」と表示すると、 本当の原因が分かりにくくなります。

12

404ページに入れたい内容

404ページは、 「見つかりませんでした」と伝えるだけでなく、 ユーザーがサイト内で迷わないように案内します。

01 404であること

ページが見つからない状態だと伝えます。

02 短い説明

削除やURL変更の可能性を案内します。

03 戻るリンク

トップや記事一覧への導線を用意します。

04 サイトらしいデザイン

通常ページと同じ世界観で整えます。

404
お探しの記事は見つかりませんでした

記事が削除されたか、 URLが変更された可能性があります。

404ページの実装例

app/not-found.tsx
import Link from "next/link";

export default function NotFoundPage() {
  return (
    <main className="not-found">
      <p className="not-found__number">
        404
      </p>

      <h1>
        お探しのページは見つかりませんでした
      </h1>

      <p>
        URLをご確認いただくか、
        以下のリンクから目的のページをお探しください。
      </p>

      <div className="not-found__links">
        <Link href="/">
          トップページへ戻る
        </Link>

        <Link href="/blog">
          記事一覧を見る
        </Link>
      </div>
    </main>
  );
}
13

よくあるつまずき

CHECK 01 notFoundをimportしていない
import { notFound } from "next/navigation";
CHECK 02 ファイル名の大文字・小文字が違う
notFound.tsx not-found.tsx
CHECK 03 notFound()を条件なしで実行している
if (!article) {
  notFound();
}

データの有無を確認したうえで実行します。

CHECK 04 通信エラーまで404として扱っている

記事が存在しない場合と、 API通信そのものが失敗した場合を分けて考えます。

CHECK 05 not-found.tsxをpages内に置いている

今回説明している方法はApp Router用です。 appフォルダー内へ配置します。

CHECK 06 404ページに戻るリンクがない
<Link href="/">
  トップページへ戻る
</Link>
CHECK 07 error.tsxと役割を混同している

データが存在しない場合はnot-found、 予期しない処理エラーはerrorとして整理します。

迷ったときは、
「正常に確認した結果、対象が存在しなかったのか?」 を判断基準にします。

14

まとめ:関数が切り替え、ファイルが表示する

notFound()とnot-found.tsxは、 どちらも404表示に関係しています。

ただし、 一方は処理を開始する関数、 もう一方は画面を作るファイルです。

今回覚えておきたいこと

  • notFound()はNext.jsが提供する関数
  • notFound()は通常のページ表示を中断する
  • not-found.tsxは404画面を定義するファイル
  • データが存在しない場合にnotFound()を実行する
  • notFound()の実行後にnot-foundのUIが表示される
  • not-found.tsxはappフォルダー内へ置く
  • ルートセグメントごとに404画面を用意できる
  • 404と予期しないエラーは分けて考える
  • 404ページには戻るためのリンクを用意する
404へ切り替える notFound() if (!article) { notFound(); }
404画面を表示する not-found.tsx export default function NotFound()

最初は、notFound()とnot-found.tsxが 同じものの別の書き方に見えました。

しかし、処理と画面を分けて考えると、 2つの役割はとてもシンプルです。

Next.js・microCMS初心者の学習記録 notFound()が404を呼び出し、
not-found.tsxがユーザーへ画面を見せます。

AILPENGINE。自動進化型AI-LP。公開後も、成果に合わせて進化する! 行動計測、分析、構成改善、成果最大化。自前計測、CTA位置最適化、レポート可視化。LP改善を相談する(相談無料)。

日本ドラフトのAIチャットボットで問い合わせ対応を効率化・自動化!24時間365日対応、簡単設定、マルチプラットフォーム対応で人件費・工数を削減。今すぐ無料で相談する

※当社は、当サイトに掲載する情報について、正確性・完全性・有用性その他一切の事項を保証するものではありません。
また、当サイトの情報をご利用いただいたことにより生じた損害、ならびに当サイトからリンクまたはバナー等を通じて移動した外部サイトにおいて提供される情報・サービス等により生じた損害について、当社は一切の責任を負いかねます。