🐡
ページ全体の再レンダリングなしでクエリパラメータを変更したい(AppRouter)
経緯
外部にも状態を保持したまま URL を共有できることが要件としてあるプロジェクトで、その要件を内部の state の一部を URL に反映したり、該当の URL にアクセスされた場合はクエリパラメータから状態を復元して表示して実現していました。
ただし、過去に React 17 + react-router で作ったプロジェクトだったので、今回 Nextjs(App Router)に載せ替えたところ、クエリパラメータを変更するとページ全体に再レンダリングが発生してしまう問題に遭遇したので、ページ全体を再レンダリングせずに状態を更新する方法を模索しました。
どこから探そう?
まずはnextjs app router change without rendering
とググってみました。
なるほど。shallow
オプションを使えるとのこと。
shallow routing(浅いルーティング)とは
データフェッチメソッドを再度実行せずに URL を変更できる仕組みとのこと。
Pages Router では shallow オプションが使える
Nextjs(Pages Router)を使用している場合は router.push の第三引数に shallow
オプションがあります。
router.push("/?counter=10", undefined, { shallow: true });
App Router ではどうしたらいい?
next app router shallow routing
でググってみると先人が智慧を書き残しておいてくださっていました。
実践
// 絶対パスを取り出す
const baseUrl = new URL(window.location.origin);
const url = new URL(`/`, baseUrl);
const query = { id: 1, param:1 }
Object.keys(query).forEach((key) => {
// 今回は複数のクエリを指定する必要があったのでループさせてsearchParamsにセット
url.searchParams.set(key, query[key]);
});
// history.pushState()を使ってクエリパラメータを更新
window.history.pushState({}, "", url);
確かにApp Routerでも全体が再レンダリングされずにクエリパラメータを変更できました。
参考
Discussion