存在しないURLにアクセスされたときや、指定されたデータが見つからなかったときに表示する「404 ページ」。Next.js の App Router では、not-found.tsx という特別なファイルを置くだけで、自分のサイトに合ったデザインの404ページを用意できます。さらに notFound() 関数を使えば、コードの中から「これは見つからなかった」と宣言して404ページを表示できます。この記事では、両者の使い方と、セグメントごとに出し分ける方法まで、初心者向けに解説します。
目次
not-found.tsx とは
not-found.tsx は、App Router で「見つからなかった」ときに表示されるUIを定義する特別なファイルです。app フォルダの中に置くと、次の2つの場面で自動的に使われます。1つは、後述する notFound() 関数が呼ばれたとき。もう1つは、どのルートにも一致しないURLにアクセスされたとき(app 直下に置いた場合)です。まずは基本の作り方から見ていきましょう。
not-found.tsx を作る
app/not-found.tsx を作成し、404ページとして表示したい内容を返すコンポーネントを書きます。ふつうのページと同じように JSX を返すだけです。
import Link from "next/link";
export default function NotFound() {
return (
<div>
<h1>404 - ページが見つかりません</h1>
<p>お探しのページは存在しないか、移動された可能性があります。</p>
<Link href="/">トップページに戻る</Link>
</div>
);
}
app 直下に置いた not-found.tsx は、サイト全体の「どこにも一致しないURL」に対する404ページになります。デフォルトの素っ気ない404画面が、自分でデザインした画面に置き換わります。
notFound() で404を出す
URLの形は正しくても、「そのIDの投稿が存在しない」ようなケースがあります。このときは next/navigation の notFound() 関数を呼ぶと、その場で処理を中断して not-found.tsx を表示できます。動的ルーティングのページでよく使うパターンです。
import { notFound } from "next/navigation";
async function getPost(id: string) {
const res = await fetch(`https://example.com/api/posts/${id}`);
if (!res.ok) return null; // 見つからなかった
return res.json();
}
export default async function PostPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const post = await getPost(id);
// データが無ければ 404 ページを表示する
if (!post) {
notFound();
}
return <h1>{post.title}</h1>;
}
notFound() は呼び出すと内部で例外を投げて処理を止めるため、その後のコードは実行されません。return notFound() と書かなくても、それより下(post.title を使う部分)には到達しない仕組みです。この関数のおかげで、「データが無ければ404」というよくある処理をすっきり書けます。
セグメントごとに404を出し分ける
not-found.tsx は app 直下だけでなく、フォルダ(ルートセグメント)ごとに置けます。たとえば app/blog/not-found.tsx を用意すると、blog 配下で notFound() が呼ばれたときには、ブログ専用の404ページが表示されます。近い階層のものが優先されるため、セクションごとに雰囲気を変えたいときに便利です。
| ファイルの場所 | 使われる場面 |
|---|---|
app/not-found.tsx | サイト全体の404(一致しないURL全般) |
app/blog/not-found.tsx | blog 配下で notFound() が呼ばれたとき |
なお、存在しないURL全般に対して app 直下以外の not-found.tsx を割り当てたい場合は、キャッチオールルート([...slug])と組み合わせて notFound() を呼ぶ、といった作り方をします。まずは app/not-found.tsx を1つ用意しておけば、サイト全体の404はカバーできます。
まとめ
Next.js の App Router では、not-found.tsx を置くだけで独自の404ページを用意できます。app 直下に置けばサイト全体の404になり、フォルダごとに置けばその配下専用の404ページにできます。データが見つからないときは next/navigation の notFound() を呼べば、その場で処理を止めて404ページを表示できます。動的ルーティングで「存在しないIDにアクセスされた」ケースは頻繁に起きるので、notFound() と not-found.tsx をセットで用意しておくとよいでしょう。