63
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Next.jsのrouter.pushとrouter.replaceの違いとそれぞれの最適な使い道

Last updated at Posted at 2021-10-04

この記事について

Next.jsの router オブジェクトに存在するメソッドの router.pushrouter.replace が似ていて、どちらを使用するのがベストなのか分からなくなる場面があった為、それぞれの違いと最適な使い道についてNext.jsの実装を参考にしながらまとめました。

router.push

構文

router.push(url, as, options)

できること

指定したリンクにぺージ遷移ができます。

router.pushの返り値の型はPromiseで、ジェネリクスで渡している型はbooleanです。

push(url: Url, as?: Url, options?: TransitionOptions): Promise<boolean>;

使用例

import { useRouter } from 'next/router'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/home')}>
      Click me
    </button>
  )
}

向いている使い方

  • プロジェクト内でページ遷移したいとき
  • ドキュメントによると外部リンクを指定する場合は、window.locationを使うと良いとの記述がありました
    • router.pushで外部リンクを指定しても、内部の実装ではwindow.location.hrefで遷移する処置を書いていたので使用しても問題なさそうです(該当コード

router.push外部URLに使用する必要はありません。
window.locationは、これらの場合に適しています。
https://nextjs.org/docs/api-reference/next/router

router.replace

構文

router.replace(url, as, options)

できること

指定したリンクにぺージ遷移ができます。

router.pushとの違いは、指定したURLをhistoryのスタックに追加せずに上書きしてページ遷移する点です。

NextはURLのhistoryをwindow.historyで管理していますが、router.replaceは直接historyを上書きする感じで実装されていそうでした(該当コード

router.replaceの返り値の型はPromiseで、ジェネリクスで渡している型はbooleanです。
router.pushの型と同一です。

replace(url: Url, as?: Url, options?: TransitionOptions): Promise<boolean>;

使用例

import { useRouter } from 'next/router'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.replace('/home')}>
      Click me
    </button>
  )
}

向いている使い方

  • ユーザに無効なURLにアクセスされた場合に、指定ページにリダイレクトするとき(/400/500等)

向いてる場面の例

仕様:ログインしないと閲覧できないページ(/profile/detail)があり、ログインしていない状態でアクセスされたら/400に遷移させる

pushの場合だとこうなります

「/profile/detail」 にアクセス → 「/400」 にリダイレクト

history: [/profile/detail, 400]

結果

/400 からブラウザバックすると/profile/detailに戻れる

replaceの場合だとこうなります

「/profile/detail」 にアクセス → 「/400」 にリダイレクト

history: [400]

結果

historyが上書きされるので/400 からブラウザバックできない

まとめ

  • 基本ページ遷移にはrouter.pushを使用するで問題ない
  • アクセス制限したいページがあり、リダイレクト処理を行う場合はrouter.replaceが向いている

おまけ

  • router.backwindow.history.backと全く同じ(該当コード

  • router.reload window.location.reloadと全く同じ(該当コード

  • Nextはスクロール位置をsessionStorageに保存してそう(該当コード

localStorage に保存されたデータに期限がないのに対して、sessionStorage に保存されたデータはページのセッションが終了するときに消去されます。
ページのセッションはブラウザを開いている限り、ページの再読み込みや復元を越えて持続します。

参考: MDN

不明だった事

  • router.pushrouter.replaceなどのメソッドがPromiseを返している理由が不明でした。どなたかご存知の方いたら教えてくださると嬉しいです!!

参考

Next.js Docs
Next.js Github

63
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
63
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?