🛣️

【Next.js】あなたはuseRouter と Router の違いを知っていますか 【next/router】

2022/10/17に公開

注意

Next.js はめちゃくちゃ変化が激しいフレームワークです。
この情報は2022/10/17時点の情報です。
変わってても怒らないでください泣

この記事の意図

これを読むと、 Next.js で画面遷移する時に使う next/router についてちょっと詳しくなれます。
useRouterRouter の違いについてです。

Next.js の Router オブジェクト (next/router)

みなさんは、Next.js でスクリプトから内部リンクの画面遷移を行う時どうしていますか?
こちらの公式ドキュメントの通り、 useRouter を使う人が多いんじゃないでしょうか。

公式ドキュメント
https://nextjs.org/docs/api-reference/next/router

だいぶ適当ですが、以下のようなコードになります。

import { useRouter } from 'next/router'

const router = useRouter()

router.push("/")

筆者も上記のコードでやります。
ただ、以下のようなコードはどうでしょうか。

import Router from 'next/router'

Router.push("/")

これ、実はどっちも問題なく動きます。
じゃあどう違うの?と疑問になったので調べました。

参考情報

こちら参考の記事です。割とここに書いてますが、もうちょい自分なりに噛み砕いて書きます。

Next.js 公式リポジトリの discussion
https://github.com/vercel/next.js/discussions/18522

Next.jsのRouterとuseRouterは何が違うのか
https://qiita.com/PonPon3/items/8f73160b658cad4fa412

明確な違い

明確な違いは、 useRouter がフックであり、 Router がただのグローバルな変数にすぎないという点です。
すなわち useRouter を参照しているコンポーネントは、ページのパスが変わるたびに再描画されます。
それに対して、 Router を参照しているコンポーネントは、ページパスが変化してもコンポーネントが再描画されることはありません。

わかりやすいサンプル

わかりやすいサンプルのコードを公開します。
yarn install && yarn dev で確認できます。
よかったら clone して動かしてみてください。

GitHub
https://github.com/yoshiishunichi/next-router-example

Layout に配置した Header を2つ用意しています。どちらの Header にも現在のパスの名前を表示しています。
1つの Header は useRouter から、もう一方は Router からパスを取得しています。
また、 _app.tsx の再描画に影響されないように2つの Header コンポーネントをメモ化しています。

実際の動作

画面遷移のたびに useRouter の方は画面に反映されますが、 Router の方は反映されません。

またそれぞれの再描画のタイミングを console.log に吐き出すようにしているので、気になる人は git clone して試してみてください。
useRouter の方はパスが切り替わるたびに console.log が吐かれ、 Router は吐かれません。

メリットとデメリット

上記から、それぞれのメリット・デメリットをまとめます。

  • useRouter
    • メリット: 画面遷移によって必ずコンポーネントの再描画が発生する
      • 常に正確なパスの情報を画面に表示できる
    • デメリット: 画面遷移のたびに不要な再描画が発生する可能性がある
      • パフォーマンスが低下する可能性がある
  • Router
    • メリット: 画面遷移による不要な再描画が起きない
      • シンプルな Router.push に使うだけの場合こちらで十分な可能性もある
    • デメリット: 必要な再描画も起きない
      • さっきのサンプルのような現在のパスを表示するような用途の場合、画面と実際のパスに違いが生じる可能性がある

結論どっち使う?

やっぱり useRouter 使っときたいなと思いますね…
先程パフォーマンスが低下する可能性があると書きましたが、画面遷移のタイミングでしか再描画は起きないので別に気にするほどじゃないと思います。
それよりも、画面から参照しているパスの情報と実際のパスに乖離が起きる方が問題な気もします。

最後に

useRouterRouter の違いを調べてその結果をまとめてみました。
質問とか、「ここはこう思います」みたいなことがあればコメントください。

普段はTwitterに生息してるので、フォローしてくれると嬉しいです。
ろくなツイートしてないですが…

https://twitter.com/ganja_tuber

では、また〜

Discussion