【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