1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js Segmentを構成するファイルの使い方

Posted at

はじめに

この記事では page.tsx, layout.tsx 以外のSegment構成ファイルに関する情報を発信します。

目次

  1. loading.tsx
  2. not-found.tsx
  3. error.tsx
  4. global-error.tsx
  5. route.tsx
  6. default.tsx
  7. 参考文献

loading.tsx

データ取得がある画面ではローディングを使用するかと思います
ここではその有効方法と確認方法を記載します。
※ストリーミングは本記事では扱いません

ローディングファイルの有効化と確認

app/
 └─ sample/
    ├─ loading.tsx
    └─ page.tsx
loading.tsx
export default function Loading(){
	return <>...loading</>;
}

通常はローディングスピナーやスケルトンでUIを記述すると思いますが、今回はこれで十分です :bird:
使用したいツリー内に上記ファイルを設置すれば OK !!

page.tsx
export default async function Page() {
  await new Promise(resolve => setTimeout(() => resolve(""), 2000));
  return (
      <div>sample</div>
  )
}

ローディングの発火を検証するための処理を加えたら、ブラウザで確認してみてください !
2秒ほど「...loading」が表示されるはずです

Good to know

  • loading.tsxへpropsは渡せない

not-found.tsx

404エラーをキャッチし、404UIを提供するファイルです
ここではその有効方法と確認方法を記載します。

404画面の有効化と確認

app/
 └─ sample/
    ├─ not-found.tsx
    └─ page.tsx
not-found.tsx
export default function NotFound() {
    return (
      <div>
        <h1>ページが見つかりません</h1>
        <p>お探しのページは存在しないか、削除された可能性があります。</p>
        <a href="/">ホームに戻る</a>
      </div>
    );
}
page.tsx
import { notFound } from "next/navigation";

export default function Page() {
    notFound();
    return (
        <div>sample not found</div>
    )
}

ブラウザで該当画面を表示すると、not-found.tsxのUIが確認できると思います :bird:
not-found.tsxを app/ に配置するとグローバルなファイルとなり、アプリ全体の404エラーをキャッチ出来るようになります。
ツリー毎に置いてもいいですが、404のUIを細かく変更する必要に迫られることは中々ないと思いますので、通常は app/ に1つ配置するのがスタンダードな配置かと思います

Good to know

  • not-found.tsxへpropsは渡せない

error.tsx

データ取得や画面の提供の際に例外が発生した場合、エラーを通達するUIを提供するファイルです
ここではその有効方法と確認方法を記載します。

エラー画面の有効化と確認

app/
 ├─ error.tsx
 └─ page.tsx
error.tsx
'use client'
 
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={() => reset()}>Try again</button>
    </div>
  )
}
page.tsx
export default function Page() {
  throw new Error("This is a test error!");
}

ブラウザで該当画面を表示すると、error.tsxのUIが確認できると思います :bird:
下記画像(公式)からも分かるようにerror.tsxは、配置した時点でErrorBoundaryのfallbackに自動的に充てられる仕組みになっています。
また、ErrorBoundaryはLayoutの内側でネストされていますので、同階層のlayout.tsxで発生したエラーはキャッチできません。最も近い親ErrorBoundaryまでバブルアップします
スクリーンショット 2024-10-13 1.37.24.png

Good to know

  • クライアントコンポーネントで定義する必要があります
  • RootLayout 内で発生したエラーのキャッチは global-error.tsxの役割となります

global-error.tsx

error.tsx同様にデータ取得や画面の提供の際に例外が発生した場合、エラーを通達するUIを提供するファイルです
global-error.js は運用環境でのみ有効となるファイルなので私自身検証できていませんが、おそらくこれで有効になるだろうというコードを記載します

エラー画面の有効化と確認

app/
 ├─ global-error.tsx
 └─ layout.tsx
global-error.tsx
"use client";

export default function GlobalError({
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <html>
      <body>
        <h2>Something went wrong!</h2>
        <button onClick={() => reset()}>Try again</button>
      </body>
    </html>
  );
}
layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const throwError = () => {
    throw new Error("This is a test error!");
  };
  throwError();
  
  return (
    <html lang="en">
      <body className={inter.variable}>
          {children}
      </body>
    </html>
  )
}

開発環境等でブラウザを開くと、「This is a test error!」が表示されます。
RootLayoutで発生したエラーはerror.tsxでキャッチできないので、global-error.tsxが活躍してくれるはずです:sweat_smile:

Good to know

  • クライアントコンポーネントで定義する
  • Segment単位で設置しないファイル
  • このUIが表示されるときはRootLayoutと置き換えられるので、html・bodyタグを記載

route.tsx

Web APIを提供するためのファイルです
App Routerで実装するWeb APIを Route Handlerと呼び、基本的には /app/api/ 配下に配置します
ここではその有効方法と確認方法を記載します。

Route Handlerの有効化と確認

.env
app/
 └─ api
    └─ sample
       └─ route.tsx
 └─ sample
    └─ page.tsx
route.tsx
import { NextResponse } from "next/server";

export async function GET(req: Request){
    const hello = [
        { "name": "北海道・東北", "value": "1", "code": "1", "children": ["北海道", "青森県", "岩手県", "宮城県", "山形県", "福島県", "秋田県"] },
        { "name": "関東", "value": "2", "code": "2", "children": ["茨城県", "栃木県", "群馬県", "埼玉県", "千葉県", "東京都", "神奈川県"] },
        { "name": "中部", "value": "3", "code": "3", "children": ["新潟県", "富山県", "石川県", "福井県", "山梨県", "長野県", "岐阜県", "静岡県", "愛知県"] },
        { "name": "近畿", "value": "4", "code": "4", "children": ["三重県", "滋賀県", "京都府", "大阪府", "兵庫県", "奈良県", "和歌山県" ] },
        { "name": "中国・四国", "value": "5", "code": "5", "children": ["鳥取県", "島根県", "岡山県", "広島県", "山口県", "徳島県", "香川県", "愛媛県", "高知県" ] },
        { "name": "九州", "value": "6", "code": "6", "children": ["福岡県", "佐賀県", "長崎県", "熊本県", "大分県", "宮崎県", "鹿児島県", "沖縄県" ] }
    ]
    return NextResponse.json({ hello })
}
page.tsx
export default async function Page() {
    const res = await fetch(
        `${process.env.URL}/api/sample`, 
        {
            method: 'GET',
        }
    );
    const data = await res.json();
    console.log(data.hello);

    return (
        <h1>sample route</h1>
    )
}
.env
URL="http://localhost:3000"

ブラウザで該当画面を表示すると、ターミナルにて画像のような出力が確認出来ると思います。
スクリーンショット 2024-10-13 20.37.53.png

default.tsx

parallel routeでのFallback UIとして使用されるファイルです。
こちらは別記事で取り上げる予定です。

参考文献

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?