hyme

Next.jsのApp Routerでクエリパラメータを変えたLinkをつくる

今回は、Next.jsのApp Routerを使っているときに、クエリパラメータを一部変更したURLをつくって next/link のLinkコンポーネントに設定するときにちょっと困ったので備忘録です。

やりたかったこと

問題になったこと

useSearchParams は、 ReadonlyURLSearchParams という URLSearchParams とは違うものを返します。

これは URLSearchParams と同じインターフェースですが、 Readonly とあるように setdelete ができないように変更されています。

(できない、というよりは実行はできるがなにも起こらない、という挙動になります。)

そして、 ReadonlyURLSearchParams は以下のように直接コンストラクタ引数には渡せないという問題がありました。

export const UpdatedLink = () => {
  const pathname = usePathname()
  const searchParams = useSearchParams()
  const clonedSearchParams = new URLSearchParams(searchParams); // これができない
  // ...

どう解決したか

ReadonlyURLSearchParams#entries からkey-valueの配列をもとに、新しく URLSearchParams をつくるようにしました。

簡単な例としては以下になります。

export const UpdatedLink = ({ children }: PropsWithChildren) => {
  const pathname = usePathname()
  const currentParams = useSearchParams()
  const entries = Array.from(currentParams.entries())
  const updatedQueryString = useMemo(() => {
    const updatedParams = new URLSearchParams(entries)
    if (updatedValue) {
      updatedParams.set('value', updatedValue)
    }
    return updatedParams.toString()
  }, [entries, startCursor])

  return <Link href={{ pathname, params: updatedQueryString }}>{children}</Link>
}

参考文献など