Next.jsの戻るボタン実装
はじめに
Next.jsの戻るボタン実装するときにレビューをもらったので、レビュー内容をまとめたいと思います。
戻るボタンの実装方法
戻るボタンの実装方法として3つあります。
- router.back()
- router.push(戻り先URL)
- <Link href="戻り先URL">
router.back()
import { useRouter } from 'next/navigation'
export function AAA({ id }: ARDetailProps) {
const router = useRouter()
const handleBack = () => {
router.back()
}
return (
<>
・・・
<Button onClick={handleBack}>戻る</Button>
</>
)
特徴
- router.back() を実行すると、前のページに戻る(ブラウザの「戻るボタン」と同じ)。
- 履歴がない場合は何も起こらない(または、デフォルトのトップページに遷移する)。
router.push(戻り先URL)
import { useRouter } from 'next/navigation'
export function AAA({ id }: ARDetailProps) {
const router = useRouter()
const handleBack = () => {
router.push('/')
}
return (
<>
・・・
<Button onClick={handleBack}>戻る</Button>
</>
)
特徴
- router.push('/') を実行すると、指定したページへ遷移する。
- 履歴が追加されるため、ブラウザの戻るボタン で前のページに戻ることが可能。
Link href="戻り先URL"
<Link href="/" className="block mr-4">
<Button>戻る</Button>
</Link>
特徴
- Linkはaタグの代替で、hrefに指定したページへ遷移する。
- 画面遷移時にページ全体を再読み込みせず、Next.jsのクライアントサイドナビゲーションを利用する。
- router.push()とほぼ同じ動作をするが、クリック時の動作がブラウザのデフォルト動作に依存する。
戻るボタンの実装方法として最適なのは?
<Link href="戻り先URL">で戻るボタンを実装するのが一番良いと思います。
ドキュメントには、このように書かれています。
Recommendation: Use the <Link> component to navigate between routes unless you have a specific requirement for using useRouter.
推奨事項: useRouterを使用する特別な要件がない限り、ルート間を移動するには <Link> コンポーネントを使用します。
ドキュメントに推奨しますと書かれているのなら使ったほうがいいでしょう!という結論です。
おまけ
import { Link } from 'lucide-react'
Linkを自動インポートしたら上記のインポート先になってしまって、デザインが下記のようになってしまいました。自動インポートには注意してください。
正しくはこちらです。
import Link from 'next/link'
他のページ遷移方法
上記の3つ以外にもredirect()という遷移方法があります。
redirect()
redirect()は、server componentsかmiddlewareで遷移ができます。
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const isLoggedIn = false // 例えば未認証ならリダイレクト
if (!isLoggedIn) {
return NextResponse.redirect(new URL('/signin', request.url))
}
return NextResponse.next()
}
import { redirect } from 'next/navigation'
export default function Page() {
const isLoggedIn = false
if (!isLoggedIn) {
redirect('/signin') // サーバー側でリダイレクト
}
return <div>Welcome!</div>
}
基本的にはserver componentsかmiddlewareでしか遷移できず、ブラウザの履歴を上書きするため、戻ることができないので「戻るボタン」の実装には適していません。
redirect()はHTMLが生成される前に処理されるため、より速いという特徴があります。
さいごに
ドキュメントに書いてあるのを知らなかったので勉強になりました。
じゃあ、useRouterとLinkの使い分けはどうするの?と思ったのですが、時間があるときにそれは記載したいと思います。
Discussion