本記事では分かりやすさを重視するため、F1 を題材として取り扱っています。
F1 Racing Teams 2021 - Ferrari, McLaren, Mercedes and more
Next.js における Link コンポーネントの基本的な使用方法は公式ドキュメントを参照してください。
next/link | Next.js
本題
例えば以下のように、URL には識別子を含めずに名前のみで構成したい、といった場合です。
https://yourhostname.com/Mercedes/Lewis-Hamilton
この URL は[オリジン]/[チーム名]/[ドライバー名]
という構成になっています。
実際のところ、こういったケースではチーム ID
やドライバー ID
も同時に遷移先に渡したい場合がほとんどだと思います。
チーム ID
やドライバー ID
などの識別子を受け取らない場合、遷移先ではチームやドライバーの情報を文字列で検索しなければならないからです。
プログラマーであれば「それは避けたい」と直感的に思うのでは無いでしょうか。
識別子を含める場合、URL は以下のようになると思います。
https://yourhostname.com/Mercedes/Lewis-Hamilton?teamId=1&driverId=1
少々ばかり冗長に見えますし、これでは名前のみで構成したいという目的が達成されていません。
コード例
この場合のコード例を以下に示します。
const url =
`/${team.teamName}/${driver.driverName}`.replace(/\s/g, "-") +
`?teamId=${team.teamId}&driverId=${driver.driverId}`;
return (
<li key={url}>
<Link href={url}>{driver.driverName}</Link>
</li>
);
パラメータはuseRouter
をラップしたカスタムフックを自作し受け取っています。
import { useRouter } from "next/router";
const useParams = () => {
const router = useRouter();
return {
teamId: router.query?.teamId ?? null,
driverId: router.query?.driverId ?? null,
};
};
export { useParams };
動作例
対処
state などを用いる方法もあると思いますが、今回は動的ルーティングを用いて解決しました。
next/link - Dynamic routes | Next.js
コード例
コード例を以下に示します。
Link
コンポーネントのhref
プロパティにクエリ文字列を付与した URL、as
プロパティに表示したい URL を設定しています。
const asUrl = `/${team.teamName}/${driver.driverName}`.replace(/\s/g, "-");
const url = `/[team]/[driver]?teamId=${team.teamId}&driverId=${driver.driverId}`;
return (
<li key={url}>
<Link href={url} as={asUrl}>
{driver.driverName}
</Link>
</li>
);
動作例
URL からクエリ文字列が取り除かれているところ以外の違いはありあません。
無事に表示上の URL からクエリ文字列を隠蔽することに成功しました。
課題
ここまで実装すれば、目的は一応達成できています。
しかし課題も見えてきました。
まず、この実装では F5 を押されたときに元の画面を表示できません。
クエリ文字列が物理的に存在しないため、画面更新後にそれらを参照することができないためです。
感想
ReactRouter でのルーティングの方法が頭にこびりついていて、ファイルシステムベースでルーティングすることになかなか馴染めず苦戦しました。
なんて思っていたら ReactRouter も新バージョンが出てるみたいですね。
書き方が少し変わってるみたいなのでこちらもキャッチアップする必要がありそうです。