【Next.js】あなたはuseRouter と Router の違いを知っていますか 【next/router】
注意
Next.js はめちゃくちゃ変化が激しいフレームワークです。
この情報は2022/10/17時点の情報です。
変わってても怒らないでください泣
この記事の意図
これを読むと、 Next.js で画面遷移する時に使う next/router
についてちょっと詳しくなれます。
useRouter
と Router
の違いについてです。
Next.js の Router オブジェクト (next/router)
みなさんは、Next.js でスクリプトから内部リンクの画面遷移を行う時どうしていますか?
こちらの公式ドキュメントの通り、 useRouter
を使う人が多いんじゃないでしょうか。
公式ドキュメント
だいぶ適当ですが、以下のようなコードになります。
import { useRouter } from 'next/router'
const router = useRouter()
router.push("/")
筆者も上記のコードでやります。
ただ、以下のようなコードはどうでしょうか。
import Router from 'next/router'
Router.push("/")
これ、実はどっちも問題なく動きます。
じゃあどう違うの?と疑問になったので調べました。
参考情報
こちら参考の記事です。割とここに書いてますが、もうちょい自分なりに噛み砕いて書きます。
Next.js 公式リポジトリの discussion
Next.jsのRouterとuseRouterは何が違うのか
明確な違い
明確な違いは、 useRouter
がフックであり、 Router
がただのグローバルな変数にすぎないという点です。
すなわち useRouter
を参照しているコンポーネントは、ページのパスが変わるたびに再描画されます。
それに対して、 Router
を参照しているコンポーネントは、ページパスが変化してもコンポーネントが再描画されることはありません。
わかりやすいサンプル
わかりやすいサンプルのコードを公開します。
yarn install && yarn dev
で確認できます。
よかったら clone して動かしてみてください。
GitHub
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
使っときたいなと思いますね…
先程パフォーマンスが低下する可能性があると書きましたが、画面遷移のタイミングでしか再描画は起きないので別に気にするほどじゃないと思います。
それよりも、画面から参照しているパスの情報と実際のパスに乖離が起きる方が問題な気もします。
最後に
useRouter
と Router
の違いを調べてその結果をまとめてみました。
質問とか、「ここはこう思います」みたいなことがあればコメントください。
普段はTwitterに生息してるので、フォローしてくれると嬉しいです。
ろくなツイートしてないですが…
では、また〜
Discussion