【Next.js】Next.js の画面遷移を実装してみる
初めに
今回は Next.js で作ったアプリケーションで画面遷移ができるように実装してみたいと思います。
Next.js における next/link next/router などを使って以下を実装します。
- 次の画面への遷移
- 次の画面への値渡し
- 前の画面への遷移
- id などに基づいた動的なルーティング
なお、Next.js に関しては歴が非常に浅いため、誤り等あれば指摘していただければ幸いです。
記事の対象者
- Next.js 初学者
- Next.js の基本的な画面遷移を実装したい方
使用技術
- Next.js : 13.5.6
目的
今回は先述の通り Next.js で基本的なページの画面遷移を実装することを目的とします。
今までは特に Flutter を用いたモバイル開発に携わることが多かったので、その辺りの違いなども共有できればと思います。
実装
実装は以下の手順で進めていきたいと思います。
- 次の画面への遷移
- 前の画面への遷移
- id などに基づいた動的なルーティング
- 次の画面への値渡し
なお、今回は Next のプロジェクト作成は完了している段階からスタートします。
1. 次の画面への遷移
この章では Firstページから Secondページに遷移する実装を行います。
最もシンプルな例として以下のようにします。
import Link from "next/link";
function First() {
return (
<div>
<h1>First</h1>
<Link href={"/second"}>Second へ</Link>
</div>
);
}
export default First;
function Second() {
return <div>Second</div>;
}
export default Second;
画面遷移を行う際は Link を使用します。
Link の href にルートを指定することで、特定のページに遷移することができます。
ここで指定するルートはプロジェクトのディレクトリ構造、ファイル名に依存します。
Firstコンポーネントを含む first.tsx は pages/first.tsxに配置します。
Secondコンポーネントを含む index.tsx は pages/second/index.tsxに配置します。

pagesディレクトリや index.js や index.tsx というファイル名は Next.js のプロジェクト内では特別な意味を持ちます。
例えば、pages/hoge/index.tsx というディレクトリ構造にした場合、Link の href に /hoge を指定することで、hoge ディレクトリに含まれる index.tsx に記述されているコンポーネントが表示されます。
先述のコードでは、これらの仕組みを利用して href に /second を指定することで index.tsx に記述されている Secondコンポーネントを表示させています。
実際にコードを実行すると以下のように正常に画面遷移ができてURLも更新されていることがわかります。

2. 前の画面への遷移
次に前の画面へ遷移する「戻るボタン」を実装してみたいと思います。
First から Second に遷移した後に First に戻る処理を行います。
pages/second/index.tsx を以下のように変更します。
import { useRouter } from "next/router";
function Second() {
const router = useRouter();
return (
<div>
<h1>Second</h1>
<button
onClick={() => {
router.back();
}}
>
戻る
</button>
</div>
);
}
export default Second;
button を押した際の処理として、router.back() を実行しています。
router は useRouter を用いたものであり、useRouter はルーティングを行うための hook です。詳しくは Next.js公式ドキュメント をご覧ください。
実行してみると以下のように Second に進んだ後、 「戻るボタン」を押すと First に戻ることができるようになっています。

useRouter から遡ると以下のようなコードがありました。
window.historyに関する記事によるとwindow.history は「ブラウザーのセッション履歴 (現在のページが読み込まれているタブまたはフレームで訪れたことがあるページ群)」とされており、back() はその履歴を一つ遡る操作であることがわかります。
class Router {
reload() {
window.location.reload();
}
/**
* Go back in history
*/ back() {
window.history.back();
}
/**
* Go forward in history
*/ forward() {
window.history.forward();
}
Flutter との比較
少し Flutter の Navigator1.0 と比較してみると、 Flutter では Navigator.pop() のように記述し、それぞれのページを次々に垂直方向に積み重ねていき、前のページに戻る場合は現在のページを跳ね除けるイメージです。
一方で今回の Router ではユーザーが訪れたページを history として、back() forward() で水平方向に移動するイメージがあります。
3. id などに基づいた動的なルーティング
まずは secondディレクトリに [id].tsx という名前のファイルを作成します。
そして中身を以下のようにします。
export default function SecondDetail() {
return <h1>Second Detail</h1>;
}
次に Firstコンポーネントを以下のように変更します。
import Link from "next/link";
function First() {
const id = "hoge";
return (
<div>
<h1>First</h1>
<p>
<Link href={"/second"}>Second へ</Link>
</p>
<p>
<Link href={`/second/${id}`}>Second Detail へ</Link>
</p>
</div>
);
}
export default First;
実行してみると以下のように正常に画面遷移し、URLは http://localhost:3000/second/hoge のように id で指定した値である hoge が入っていることがわかります。

Link の href でディレクトリ名の後に、作成したファイル名と同じ名前の変数を渡すと、その変数に入っている値がルートとなるページを表示させることができます。
なお、Link の href に関して、href={`/scd/${id}`} のようにディレクトリ名を間違えた場合は動作しなくなるので、タイプミスには注意が必要です。
4. 次の画面への値渡し
先程の実装では id を用いた動的な遷移を実装しました。しかし、次のページに値を渡すところまではできていなかったので、単にURLが変更されただけでした。この章では、次のページに値を渡して、ページごとに異なる内容を表示させてみます。
まずは First を以下のように変更します。
import Link from "next/link";
const skills = [
{ id: "1", name: "Dart", proficiency: 5 },
{ id: "2", name: "Swift", proficiency: 4 },
{ id: "3", name: "TypeScript", proficiency: 3 },
{ id: "4", name: "Python", proficiency: 3 },
];
function First() {
return (
<div>
<h1>First</h1>
{skills.map((skill) => (
<p>
<Link
href={{
pathname: `/second/${skill.id}`,
query: {
id: skill.id,
name: skill.name,
proficiency: skill.proficiency,
},
}}
>
{skill.name}
</Link>
</p>
))}
</div>
);
}
export default First;
この変更では、skills として各スキルの id, name, proficiency を保持するデータを用意します。実際のユースケースではデータベースから取得してきたJSON形式のデータなどが考えられます。
次に登録した skills の数だけリンクを作成し、 pathname: `/second/${skill.id}`, とすることで各スキルに登録されている id に応じた遷移を行います。
そして、以下のように query としてそれぞれの値を割り当てて、次のページに値を渡すことができます。
query: {
id: skill.id,
name: skill.name,
proficiency: skill.proficiency,
},
次に First から値を受け取る SecondDetail に関して、以下のように変更します。
import { useRouter } from "next/router";
export default function SecondDetail() {
const router = useRouter();
return (
<div>
<h1>{router.query.name}</h1>
<p>{`熟練度: ${router.query.proficiency}`}</p>
</div>
);
}
先程の章でも使った useRouter() を用いて、渡された値を受け取ることができます。
router.query で、前のページから渡された query にアクセスすることができ、それぞれのスキルの値を引き出して表示させることができます。
実行してみると以下のように各ページごとのURLになり、値も次のページに渡せていることがわかります。
また、URLも各スキルに応じて変更されていることがわかります。
これで値渡しは完了です。

まとめ
最後まで読んでいただいてありがとうございました。
今回は Next.js の画面遷移についてまとめました。
今回紹介した機能以外にも、さまざまなオプションがあるので、今後触れてみたいと思います。
誤っている点や他の実装方法等あればご指摘いただけると幸いです。
参考
Routing
useRouter
window.history
Discussion