📚

Next.jsで今の場所(current url)を判定して表示を変える

2021/06/29に公開約1,800字

よくナビゲーションメニューなどで、今いる場所の色が変わる表現がありますが、それをNext.jsで実現する方法です。

Next.jsにはuseRouterというhookが用意されているので、それを使うと簡単でした。

Next.jsドキュメント:next/router

方法は簡単です。

  • アクセスしたページのurlを取得
  • urlとナビ内のhrefを判定
  • 反映するcssを切り替える

これでナビ内の現在ページをハイライトすることができます。

urlを取得する方法

import { useRouter } from "next/router";

const Nav = () => {
  const router = useRouter(); 

  console.log(router.pathname)
  // http://localhost:3000/a/b ⇒ /a/b

useRouterを使うことで表示ページのURLを取得することができます。

useRouterのオブジェクト

useRouterにはオブジェクトが定義されています。

  • pathname:文字列でドメイン以降のpathが取得できます。パラメータやクエリは取得できません
  • query:動的ルーティングをしている[id]を{ id: 'なかみ' }で取得できます
  • asPath:ブラウザに表示されるパスを文字列で取得できます。パラメータも取得できます

pathname

router.pathnameで、そのページのパスを取得できます。

ただ、Next.jsの動的ルーティングの中身([id]のid部分)を取得することはできません。

http://localhost:3000/a/b?a=100のbが[id]だった場合、取得できる文字列は/a/[id]になります。

パラメータも取得できないので、使うケースは限られます。

asPath

router.asPathとすることで[id]の中身も文字列で取得できます。

ブラウザに表示されるものをそのまま取得できるのです。

http://localhost:3000/a/b?a=100のbが[id]でも、取得できる文字列は/a/b?a=100になります。

日本語urlだと文字化けするのでdecodeURI(router.asPath)などで取得するほうが後々の判定で使いやすいです。

query

router.queryとすることで、オブジェクトとして動的ルーティングの中身を取得できます。

http://localhost:3000/a/b?a=100のbが[id]の場合{ id: 'b' }として取得できます。

リンクのclassを切り替える

//抜粋
  <Link href={href}>
    <a
      className={
	router.pathname.startsWith(href)
	  ? "current"
	  : "non-current"
      }
    >
      {リンクが貼られる文字列}
    </a>
  </Link>
 //抜粋

これは一例です。

ナビを作る際に、配列でデータを渡してmapとかforeachでのループとかで作るのをよく見ますが、その中身のリンク部分だけ、みたいな例です。

Linkで設定しているhrefuseRouterで取ってきたurlを判定して、trueなら"current"をfalseなら"non-current"というクラスをつけることで表示を変えます。

例ではstartsWithを使っていますが、router.pathname === hrefとして等価でも良いですし、動的ルーティングの場合はpathnameではなくasPathを使うでしょうし…、という感じでその時々で必要な判定を入れます。

"current"と"non-current"で文字色を変えたり、背景色を変えておくことで、表示を変えることができます。

Discussion

ログインするとコメントできます