在 Next.js 中如何使用 Router 偵測當前鏈接並給予其一個類別,以便我們可以使用 CSS 來為其設置樣式。

當與鏈接一起工作時,一個非常重要的功能就是確定當前 URL,特別是為活動鏈接指定一個類別,以便我們可以將其與其他鏈接區分開來並進行不同的樣式設定。

這在網站的標頭中特別有用。

Next.js 預設的 Link 組件(next/link)並不會自動為我們完成這個功能。

我們可以使用兩種技術。一種是將邏輯添加到 Link 的子組件中。另一種技術是在另一個我們可以構建的組件中使用 Link 來處理此邏輯。

讓我們從最簡單的方法開始:

import React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'

const menu = [
  { title: '首頁', path: '/home' },
  { title: '探索', path: '/explore' },
  { title: '通知', path: '/notifications' },
]

const Sidebar = () => {
  const router = useRouter()

  return (
    <div>
      {menu.map((item, index) => {
        return (
          <Link key={index} href={item.path}>
            <a
              className={`cursor-pointer ${
                router.pathname === item.path
                  ? 'text-blue-500'
                  : 'hover:bg-gray-900 hover:text-blue-500'
              }`}
            >
              {item.title}
            </a>
          </Link>
        )
      })}
    </div>
  )
}

export default Sidebar

我建議使用這種方法,因為它是最簡單的方法。

另一種技術是創建自己的 Link 組件,並將其存儲在 /components 文件夾下的 MyLink.js 文件中,然後導入它而不是默認的 next/link

在組件中,我們確定當前路徑名是否與該組件的 href prop 相匹配,如果是,則將 text-blue-500 類附加到其子組件上。

當然,你可以使用自己定義的類名。這裡使用的是 Tailwind 的類名,將文本設置為藍色。

最後,我們使用 React.cloneElement() 返回具有更新類別的子組件:

import React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'

const MyLink = ({ href, children }) => {
  const router = useRouter()

  let className = children.props.className || ''
  if (router.pathname === href) {
    className = `${className} text-blue-500`
  }

  return <Link href={href}>{React.cloneElement(children, { className })}</Link>
}

export default MyLink

現在,我們可以在其他組件中使用這個 MyLink 組件:

import MyLink from 'components/MyLink'

// ...
<MyLink
  href={'blog'}
>
  <a>博客</a>
</MyLink>
<MyLink
  href={'about'}
>
  <a>關於</a>
</MyLink>

在這種情況下,與第一種技術相比,“用戶”代碼更簡單,因為你將邏輯放在了 MyLink 內部。