Next.jsのルーティングとページ移動
![投稿日](https://infigate.net/wp-content/themes/infigate/img/icon/edit_note.png)
![更新日](https://infigate.net/wp-content/themes/infigate/img/icon/update_note.png)
はじめに
この記事の対象者
・Next.js初心者
・Next.jsの環境ができている方
Reactについて
Reactは基本的に単一ページ上でのUI操作が行われるように設計されているため、Reactでページを遷移する際は、単一のページ上のDOMを再レンダリングすることによって実現しています。このような仕組みを「SPA(Single Page Application)」と呼びます。また、Reactには仮想DOMというレンダリング機構が備わっているため、この仮想DOMと実際のHTML上のDOMを比較したときに出てくる違いのみが毎回HTML上に再描画されます。そのため、更新をした際に必要な部分しか更新されないため非常に早い速度を実現させることができます。
ReactとNext.jsの違い
Next.jsとはReactのフレームワークです。Reactではクライアント側でレンダリングを行うSPA開発が特徴ですが、Next.jsを使用することでサーバー側でのレンダリングを行うことができます。SPAでクライアント側へ空のHTMLを返し、実際のページのコンテンツはJavaScriptを使って生成します。
そのため一度ページを読み込んでしまえばページ遷移毎にサーバーへのリクエストが発生することがないため高速で動作させることができます。しかし、JavaScriptのサイズが大きくなればなるほど初回表示の読み込みには時間がかかります。
それに対して、Next.jsではアプリケーションを事前にページ単位でレンダリングしSSR(Server Side Rendering)のためクライアントのリクエストに対してサーバー側でデータを取得してHTMLを生成し、クライアント側に返します。
サーバー側でHTMLを生成するため、SEO(Search engine optimization (検索エンジン最適化))やOGP(Open Graph Protocol)に対応可能であり、初期表示も高速になります。
Next.jsは複数ページのWebアプリも作ることができます。Webアプリケーションのフレームワークでは、複数のページを作成しそれらに決まったURLを割り当ててアクセスできるようにする仕組みを「ルーティング」と言います。Next.jsにはいくつかのルーティングの仕組みが用意されています。
Appルーティング
Next.jsのWebページは「src」内の「app」というディレクトリにファイルが用意されています。この「app」ディレクトリがアプリケーションのルートとなります。
別のページを作成するときはこの「app」内に新たなディレクトリを作成し、そこにpage.tsxファイルを用意してコンポーネントを記述します。
このpage.tsxはディレクトリ名のパスにアクセスした時に表示されるようになっています。例えば「test」というディレクトリを作成した場合/testにアクセスするとその中のpage.tsxが表示されるようになります。
別のページを作成する
前回作成したTODOリストのページに別のページを追加してみます。ここでは例として「other」というページを作成します。まずはディレクトリを作成しましょう。「app」ディレクトリ内に「other」というディレクトリを作成し、その中にpage.tsxを作成します。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-14.10.55.png)
ではpage.tsxを記述していきましょう。まずは「app」ディレクトリ内のpage.tsxを開き以下を追記します。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-14.30.28.png)
続いて、新たに作成した「other」ディレクトリ内のpage.tsxを編集します。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-14.35.48.png)
すると下記のようにTOPページとotherページを行き来できるようになります。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-14.38.21.png)
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-14.38.35.png)
publicディレクトリ
ページを構成するコンポーネントは「app」ディレクトリ内に用意されますが、それ以外の静的コンテンツ(例えば画像ファイル)は「public」ディレクトリに配置されます。実際に「sample.jpeg」というファイルを用意して「public」ディレクトリ配下に配置してみましょう。
![](https://infigate.net/wp-content/uploads/2024/06/sumple.jpeg)
では配置したイメージを表示するページを作成しましょう。今回は「other」ディレクトリ内のpage.tsxを修正してみます。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-15.06.34.png)
以下のようにイメージが表示されました。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-15.08.32.png)
ダイナミックルーティング
ファイルシステムルーティングはディレクトリ分けしてpage.tsxを配置するだけでページを作れるため非常に扱いが簡単です。しかしこれはページが静的なパスに配置されているからです。例えば、データから特定の項目を取り出して表示するようなページを考えてみましょう。
こうしたものの場合、/data/1というように取り出すデータの番号をつけてアクセスするようなことがあります。この/1の部分は取り出すデータによって変化します。2番目のデータなら/2となるし、100番目のデータなら/100となるわけです。
このようなページの場合「data」ディレクトリの中に「1」から「100」までディレクトリを用意するわけにはいきません。必要に応じて/1の部分をうまく処理できるようなルーティングの仕組みが必要です。
こうした場合のためにNext.jsに用意されているのがダイナミックルーティングという機能です。これは特殊な形でディレクトリ名を用意することで、パスの一部をパラメーターとして受け取れるようにするものです。例えば/abc/hogeにアクセスしたいとき、hogeの部分を値としてコンポーネントに渡せるようにするということです。
これにより、/abc/◯◯とアクセスすれば◯◯の値を受け取って処理できるようになります。このダイナミックルーティングを利用するのに必要なことはただ指定の形式でディレクトリ名をつけることだけです。
では実際にサンプルを作成しながら使い方を見てみましょう。ここでは/nameというパスでアクセスできるようにしてみます。例えば/name/taroにアクセスすれば「taro」という名前がパラメータとして渡されるようにするわけです。
では「app」ディレクトリ内に「name」という名前でフォルダーを作成してください。そしてこの「name」ディレクトリの中にさらに「[name]」という名前でディレクトリを作ります。これがパラメーターとして値が渡されるディレクトリです。
このように[◯◯]というように名前の前後を[]で括った名前をつけるとそのディレクトリはパラメーターとして認識されるようになります。ページの処理はこの「[name]」ディレクトリの中にpage.tsxというファイルを作成して記述します。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-15.47.58.png)
では「[name]」内のpage.tsxに以下のようなコードを記述してください。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-15.54.12.png)
そしたら/name/taroにアクセスしてみましょう。「あなたは「taro」ですね。」と表示されアクセスしたパスの値が渡され利用されていることがわかります。
ここでの最大のポイントは関数に用意されている引数です。これは以下のようになっています。
{params}:{params:{name: string}}
{params}が引数に用意されている変数の部分で{params:{name:string}}は型(タイプ)の指定です。つまり「nameプロパティを持つオブジェクトがparamsプロパティに渡されるオブジェクト」が型として指定されていた、ということです。{params}というのがオブジェクトの分割代入などに記載されるのと同じ書き方です。つまりこのオブジェクト型のparamsの値が{}内のparamsに渡されるようになっていたのですね。
paramsの型指定となっている{name:string}の値は必ずパラメータとして渡される値の名前を指定します。このpage.tsxは[name]というディレクトリに用意されていました。これによりパスの一部をnameという名前で取り出すようになります。したがってparamsの型指定には{name:string}というようにnameプロパティのあるオブジェクトとして用意する必要があります。こうして引数が渡せたらなあとはparamsからnameの値を取り出し{params.name}というように表示させるだけです。
パラメーターを指定しない場合
これで/nameの後に名前をつけて/name/◯◯とアクセスしてパラメーターを受け取れるようになりました。ではパラメーターを付けなかった場合どうなるでしょうか。/nameとアクセスした場合には404エラーが発生します。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-16.15.33.png)
理由は「name」ディレクトリにpage.tsxが用意されていないからです。
では「name」ディレクトリにpage.tsxを追加してみましょう。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-16.23.18.png)
/nameにアクセスすると以下のような画面となります。
![](https://infigate.net/wp-content/uploads/2024/06/スクリーンショット-2024-06-11-16.23.48.png)
ダイナミックルーティングを利用してパラメータを使う場合、パラメータ用の[◯◯]というディレクトリだけでなくこの[◯◯]が置かれているディレクトリにもpage.tsxを用意することでエラーなく表示が行えるようになります。
さいごに
ReactとNext.jsの違いやルーティングの方法はわかったでしょうか?Webアプリケーションを開発する際はそのページやアプリケーションにあった最適なフレームワークを選定することが大切です。