
今回は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のナビゲーションについて紹介します。
それでは!