Next.jsのApp Routerでクエリパラメータを変えたLinkをつくる
今回は、Next.jsのApp Routerを使っているときに、クエリパラメータを一部変更したURLをつくって next/link
のLinkコンポーネントに設定するときにちょっと困ったので備忘録です。
やりたかったこと
- クエリパラメータを一部変えたURLをつくる
- つくったURLを
next/link
のLinkコンポーネントに設定したい
問題になったこと
useSearchParams
は、 ReadonlyURLSearchParams
という URLSearchParams
とは違うものを返します。
これは URLSearchParams
と同じインターフェースですが、 Readonly
とあるように set
や delete
ができないように変更されています。
(できない、というよりは実行はできるがなにも起こらない、という挙動になります。)
そして、 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>
}