useRouter()とは? Linkとの違いとページ遷移の基本を初心者向けに解説
Next.jsでページを移動するときは、
Linkのほかに
useRouter()を使う方法があります。
どちらもページ遷移に使えますが、
「通常のリンクを表示したいのか」
「処理の結果に応じて移動したいのか」によって
適した方法が異なります。
今回は、Linkとの違いを確認しながら、
push()、replace()、
back()、refresh()の役割を整理します。
LinkがあるのになぜuseRouterを使うの?
Next.jsでは、通常のページリンクを作るときに
Linkを使います。
import Link from "next/link";
export default function Page() {
return (
<Link href="/blog">
記事一覧を見る
</Link>
);
}
一方で、次のようなコードを見かけることもあります。
"use client";
import { useRouter } from "next/navigation";
export default function Button() {
const router = useRouter();
return (
<button
onClick={() => router.push("/blog")}
>
記事一覧を見る
</button>
);
}
どちらも/blogへ移動するなら同じでは?
移動先は同じですが、 ページ遷移を開始する方法が異なります。
ページ内に移動先を示すリンクを 表示したい場合に使います。
条件判定やフォーム送信後など、 JavaScriptの処理から移動します。
useRouter()とは?
useRouter()は、
Next.jsが提供するReactのフックです。
App Routerでは、
next/navigationから読み込みます。
ボタン操作、フォーム送信、条件判定などをきっかけに ページを移動できます。
useRouter()から取得できるもの
const router = useRouter();
ここで取得したrouterには、
ページ遷移を操作するためのメソッドが入っています。
push()
別ページへ移動
replace()
履歴を置き換えて移動
back()
前のページへ戻る
forward()
次のページへ進む
refresh()
現在のルートを更新
prefetch()
移動先を先に読み込む
useRouter()にはClient Componentが必要
App Routerのコンポーネントは、 特に指定しなければServer Componentとして扱われます。
しかし、useRouter()はブラウザー上の操作に反応するフックなので、 Client Component内で使用します。
"use client";
from "next/navigation"
"use client";
import { useRouter } from "next/navigation";
export default function NavigationButton() {
const router = useRouter();
return (
<button
onClick={() => router.push("/blog")}
>
記事一覧を見る
</button>
);
}
"use client";は、
import文よりも前のファイル先頭へ書きます。
useRouter()の基本的な使い方
基本的な流れは4段階です。
"use client";
next/navigation
const router = useRouter();
router.push("/blog");
"use client";
import { useRouter } from "next/navigation";
export default function Button() {
const router = useRouter();
const handleClick = () => {
router.push("/contact");
};
return (
<button onClick={handleClick}>
お問い合わせへ進む
</button>
);
}
useRouter()
ルーターを取得
handleClick
クリック後の処理
router.push()
移動を実行
onClick
ボタンと処理を接続
LinkとuseRouter()の違い
LinkとuseRouter()はどちらもサイト内の移動に使えますが、 用途が異なります。
- ヘッダーメニュー
- 記事タイトル
- パンくずリスト
- 一覧へ戻るリンク
- 詳しく見るリンク
- フォーム送信完了後
- ログイン成功後
- 確認ダイアログの結果
- 条件に応じた移動
- 戻るボタンの処理
router.push()で別ページへ移動する
router.push()は、
useRouter()で最もよく使うメソッドです。
移動後にブラウザーの戻る操作をすると、 元のページへ戻れます。
router.push("/blog");
動的なURLへ移動する
const articleId = "abc123";
router.push(`/blog/${articleId}`);
/blog/
abc123
/blog/abc123
検索条件をURLへ入れる
const keyword = "Next.js";
router.push(
`/search?keyword=${encodeURIComponent(keyword)}`
);
router.replace()で履歴を置き換える
router.replace()も別ページへ移動しますが、
push()とはブラウザー履歴の扱いが異なります。
戻る操作でログイン画面へ戻れます。
戻る操作でログイン画面へ戻りにくくなります。
router.replace("/mypage");
一覧から詳細へ移動する場合など。
ログイン後や完了画面への移動など。
back()とforward()で履歴を移動する
useRouter()では、 ブラウザーの戻る・進む操作に相当する処理も実行できます。
router.back()
前のページへ戻る
router.forward()
次のページへ進む
"use client";
import { useRouter } from "next/navigation";
export default function BackButton() {
const router = useRouter();
return (
<button onClick={() => router.back()}>
前のページへ戻る
</button>
);
}
back()は特定のURLへ移動するのではなく、 ユーザーのブラウザー履歴を1つ戻ります。 必ず記事一覧へ戻したい場合は、 Linkやpush()でURLを明示します。
router.refresh()とは?
router.refresh()は、
現在表示しているルートを更新するためのメソッドです。
ブラウザーでページ全体を再読み込みする操作とは異なり、 現在のルートについてサーバーから新しい内容を取得し、 必要な部分を更新します。
const handleUpdate = async () => {
await updateArticle();
router.refresh();
};
router.refresh()window.location.reload()router.prefetch()とは?
router.prefetch()は、
ユーザーが移動する可能性のあるルートを
あらかじめ読み込むためのメソッドです。
router.prefetch("/contact/confirm");
ただし、通常のLinkでは、 移動先のプリフェッチが組み込まれています。 そのため、一般的なナビゲーションのためだけに useRouter()とprefetch()を使う必要はありません。
フォーム送信後にページを移動する
useRouter()が特に役立つ例が、 フォーム送信後のページ遷移です。
"use client";
import { FormEvent } from "react";
import { useRouter } from "next/navigation";
export default function ContactForm() {
const router = useRouter();
const handleSubmit = async (
event: FormEvent<HTMLFormElement>
) => {
event.preventDefault();
const response = await fetch("/api/contact", {
method: "POST",
body: new FormData(event.currentTarget),
});
if (response.ok) {
router.push("/contact/complete");
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
name="name"
required
/>
<button type="submit">
送信する
</button>
</form>
);
}
router.push()
setError()
microCMSを使ったサイトでの使用例
microCMSの記事一覧では、 記事カードそのものが通常のリンクであれば Linkを使うのが基本です。
記事カードはLinkを使う
import Link from "next/link";
export default function ArticleCard({
article,
}: {
article: {
id: string;
title: string;
};
}) {
return (
<Link href={`/blog/${article.id}`}>
<article>
<h2>{article.title}</h2>
</article>
</Link>
);
}
条件を確認してから移動する場合
"use client";
import { useRouter } from "next/navigation";
export default function EditButton({
articleId,
}: {
articleId: string;
}) {
const router = useRouter();
const handleClick = () => {
const confirmed = window.confirm(
"この記事を編集しますか?"
);
if (confirmed) {
router.push(`/admin/blog/${articleId}/edit`);
}
};
return (
<button onClick={handleClick}>
編集する
</button>
);
}
外部サイトへの移動には何を使う?
LinkやuseRouter()は、 主にNext.jsサイト内のルート移動に使います。
別のドメインにある外部サイトへ移動する場合は、
通常のaタグを使うのが基本です。
<a
href="https://example.com"
target="_blank"
rel="noopener noreferrer"
>
外部サイトを見る
</a>
/blog
router.push("/complete")
https://example.com
外部から受け取ったURLをそのまま渡さない
router.push()やrouter.replace()へ渡すURLは、 信頼できる値だけを使用します。
フォーム入力やURLパラメータなど、 ユーザーが変更できる文字列を そのまま移動先として使うのは避けます。
router.push(userInput);
入力された値を無条件で使用する。
const allowedPaths = [
"/",
"/blog",
"/contact",
];
if (allowedPaths.includes(path)) {
router.push(path);
}
サイト内で許可したパスだけを使う、 IDをURLへ組み立てる前に形式を確認するなど、 移動先を制御します。
よくあるつまずき
"use client";
import { useRouter } from "next/navigation";
from "next/router"
→
from "next/navigation"
appフォルダーを使うApp Routerでは、 next/navigationから読み込みます。
export default function Button() {
const router = useRouter();
return (
<button
onClick={() => router.push("/blog")}
>
移動する
</button>
);
}
onClick={router.push("/blog")}
→
onClick={() => router.push("/blog")}
<Link href="/blog">
記事一覧を見る
</Link>
移動先が最初から決まっている通常のリンクには、 Linkを使います。
戻る履歴を残すならpush()、 現在の履歴を置き換えるならreplace()です。
back()の移動先は、 ユーザーがそのページへ来るまでの履歴によって変わります。
キャッシュやデータ更新処理の状態によっては、 refresh()を実行しても取得結果が変わらない場合があります。
まとめ:リンクと処理による移動を使い分ける
LinkとuseRouter()は、 どちらもNext.jsのページ遷移に使います。
ただし、通常のナビゲーションを表示するのか、 JavaScriptの処理から移動するのかによって 役割が異なります。
今回覚えておきたいこと
- useRouter()は処理からページ遷移を操作するフック
- App Routerではnext/navigationから読み込む
- useRouter()はClient Component内で使う
- 通常のリンクにはLinkを使う
- router.push()は履歴を追加して移動する
- router.replace()は履歴を置き換えて移動する
- router.back()はブラウザー履歴を戻る
- router.refresh()は現在のルートを更新する
- router.prefetch()は移動先を先に読み込む
- 外部サイトへの移動にはaタグを使う
- 信頼できないURLをrouterへ渡さない
<Link href="/blog">
router.push("/blog")
最初は、LinkとuseRouter()のどちらを使っても 同じページへ移動できるため、 違いが分かりにくく感じました。
しかし、「リンクを表示したいのか」 「処理から移動を命令したいのか」で分けると、 使い分けはシンプルです。
処理と連動する移動はuseRouter()を使います。