Next.jsを少しずつ理解していく4【ルーティング機能】

今回はNext.jsのルーティング機能について紹介します。Next.jsはpagesディレクトリのファイル・ディレクトリ構成がそのままルーティングに対応しています。

この記事では、基本のルーティング、ネストルーティング、ダイナミックルーティング、ネストダイナミックルーティング、ルーティングの取得について解説しています。

その⓪|Next.jsのプロジェクトを作る

(環境構築が完了している人は次章「その①」に進んでください)

Next.jsの環境構築については以下の記事で解説しています。

その①|Next.jsの基本ルーティング

Next.jsは、pagesフォルダ内のファイル(またはディレクトリ)構成に対応してルーティングを行います。実際に確認してみましょう。

 

pagesフォルダ内に、product.jsファイルを作成します。

Terminal

touch pages/product.js

pages/product.js

function Product() {
 return <h2>Product Page</h2>
}

export default Product

 

ブラウザでlocalhost:3000/productにアクセスすると、たった今作成したページが表示されます。

その②|Next.jsのネストルーティング

Webアプリを作成していると○○○.com/product/1の様に、productページのさらに奥にページを用意して、いわゆる「入れ子(ネスト/Nest)構造」を実現したい場合があります。Next.jsでは、pagesフォルダ内に任意のディレクトリを用意し、その中にJSファイルを作成することでネストルーティングを実現できます。

 

まずはpagesフォルダ内にproductディレクトリ、productディレクトリ直下にindex.jsファイルを作成します。

※その①で作成したpages/product.jsファイルはあらかじめ削除してください

Terminal

mkdir product
touch pages/product/index.js

/pages/product/index.js

function Product() {
 return <h2>Product Page (Nest)</h2>
}

export default Product

 

先ほど同様、localhost:3000/productにアクセスすると「Product Page (Nest)」と表示されるはずです。(表示されない場合、その①で作成したproduct.jsファイルを削除してから再度試してください)

続いては、入れ子ページを実現するためにproductディレクトリの中に1.jsファイルを作成します。

Terminal

touch pages/product/1.js

pages/product/1.js

function Product_1() {
 return <h2>Details about product 1</h2>
}

export default Product_1

 

localhost:3000/product/1にアクセスすると、「Details about product 1」と表示されます。

その③|Next.jsのダイナミックルーティング

○○○.com/product/1の様なネストルーティングを行う場合、入れ子ページをすべて手動で作成するのは面倒です。例えば、productディレクトリの入れ子ページを1~100まで用意する必要がある場合は1.js、2.js、、、100.jsという具合です。

Next.jsではproductディレクトリ直下に特殊なファイルを用意することで、リクエストされたパスに応じて動的にページを生成する「ダイナミックルーティング」を実現することができます。

 

productディレクトリ直下に、[productId].jsファイルを作成します。ファイル名をカッコ[]で囲うことで、ダイナミックルートを設定できます。

Terminal

touch pages/product/[productId].js

pages/product/[productId].js

import {useRouter} from 'next/router'

function ProductDetail() {
 const router = useRouter()
 const productId = router.query.productId
 return <h1>Details about Product {productId}</h1>
}

export default ProductDetail

 

今回は、動的にページが生成されていることをわかりやすく確認するため、useRouterフックを用いてリクエストされたページのパス(生成されたページのファイル名)を取得して表示しています。

これで、JSファイルを1~100まで手動で用意する必要はなくなりました。

その④|Next.jsのネストダイナミックルーティング

○○○.com/product/1/review/1の様に動的に生成されたproduct/1ページに対し、さらにreview/1という入れ子構造のページを動的に生成する方法について紹介します。

 

まずは、その③で作成したpages/product/[productId].jsファイルを削除してください。続いてpages/Productディレクトリの中に[productId]ディレクトリを用意し、その中にindex.jsファイルを作成します。

ここまでは、その③までの表示結果と変わりありません。

Terminal

rm -r pages/product/[productId].js
mkdir pages/product/[productId]
touch pages/product/[productId]/index.js

pages/product/[productId]/index.js

import {useRouter} from 'next/router'

function ProductDetail() {
 const router = useRouter()
 const productId = router.query.productId
 return <h1>Details about product {productId}</h1>
}

export default productDetail

 

続いて、pages/product/[productId]ディレクトリの中にreviewディレクトリを用意し、その中に[reviewId].jsファイルを作成します。

Terminal

mkdir pages/product/[productId]/review
touch pages/product/[productId]/review/[reviewId].js

pages/product/[productId]/review/[reviewId].js

import {useRouter} from 'next/router'

function Review() {
 const router = useRouter()
 const {productId, reviewId} = router.query
 
return <h1>Review {reviewId} for product {productId}</h1>
}

export default Review

 

これで、任意のproductページに対するreviewページを動的に生成することができるようになりました。

その⑤|すべてのルーティングをキャッチする

さて、最後に任意のディレクトリ以降のネストされたルーティング(あるいはURLパス)をキャッチして利用する方法について紹介します。

ダイナミックルーティングでは、1つ目の固定されたパス(product)に続く無数のパス(/1、/2...../100)に対して自動でページを生成していました。しかしこの方法では、1つ目のパスも無数に選択肢がある場合、いくつも[example]フォルダとその中のindex.jsフォルダを作成する必要があるため不便です。また、パスが3つ4つ5つと続く場合、何層にも[example]フォルダを作成する必要があります。

 

Next.jsでは、ファイル名の先頭に3つのドット(...)をつけてカッコ([])で囲むことで、そのファイルが存在するディレクトリ以降のネストされたルーティング(あるいはURLパス)をキャッチすることができます。

つまり、[...example].jsファイルが存在するディレクトリ(パス)以降のパスが無数であっても、それらに対し自動でページを生成することができるのです。

 

実際にやってみましょう。まずはpagesフォルダ直下にdocsディレクトリを用意し、その中に[[..params]].jsファイルを作成します。

Terminal

mkdir pages/docs
touch pages/docs/[[...params]].js

[[...params]].js

import {useRouter} from 'next/router'

function Doc() {
 const router = useRouter()
 const {params = []} = router.query
    
 return (
  <>
   <h1>Docs Page</h1>
   <ul>
    {params.map((x, id) => {
     return <li key={id}>{x}</li>
    })}
   </ul>
  </>
 );
}

export default Doc

 

ここで、例えばlocalhost:3000/docs/brother/sisterにアクセスしてみると、docs以降のルーティングがキャッチされて「brother」と「sister」が表示されます。

/docs以降のパスに、どのようなパスをいくつ指定してもダイナミックにページを生成します。

このように、ファイル名を[[...example]]とすることで、そのディレクトリ以降のルーティングをキャッチして好きなように活用することができます。フレキシブルなルーティングの実現だけでなく、URLパラメータとしても活用することが可能です。

まとめ

以上でNext.jsのルーティング機能の紹介は終わりです。

pagesのディレクトリ・ファイル構成がそのままルーティングに対応してくれる点は、Reactの複雑なルーティング(react-router-dom)に比べると嬉しいポイントですね。

 

次回はNext.jsのナビゲーションについて紹介します。

それでは!

コメントを残す

CAPTCHA