JavaScriptでクエリパラメーターを書き換える
実装コード
コピー&ペーストで動くJavaScriptのコードとしては次のようになります。 DevToolsに貼り付けで動作確認が可能です。
const stringify = (targetObject) => {
return Object.entries(targetObject).reduce((queries, current) => {
const key = encodeURIComponent(current[0]);
const value = encodeURIComponent(current[1]);
return (queries += (queries === "" ? "" : "&") + `${key}=${value}`);
}, "")
}
const updateQueryParams = (newKey, newValue) => {
const searchParams = new URLSearchParams(window.location.search);
const nextQueryParams = {};
searchParams.forEach((value, key) => {
nextQueryParams[key] = value;
});
nextQueryParams[newKey] = newValue;
history.replaceState(null, document.title, `?${stringify(nextQueryParams)}`);
}
TypeScriptバージョン
TypeScriptを利用している場合、大抵の場合はwebpackを通していると考えられるので、stringify
は少し楽をします。
import { stringify } from "querystring";
const updateQueryParams = (newKey: string, newValue: string): void => {
const searchParams = new URLSearchParams(window.location.search);
const nextQueryParams: { [key: string]: string } = {};
searchParams.forEach((value, key) => {
nextQueryParams[key] = value;
});
nextQueryParams[newKey] = newValue;
history.replaceState(null, document.title, `?${stringify(nextQueryParams)}`);
}
解説
URLSearchParams
URLSearchParams
を利用してクエリパラメーターを扱いやすくします。
ただしこのAPIはInternet Explorerで未サポートであり、Safariも10以下は未サポートとなっています。
が、そういったブラウザやバージョンは進化の妨げになるので切り捨てましょう。
もし対応が必要ならURLSearchParams Polyfilを充てましょう。
const searchParams = new URLSearchParams(window.location.search);
現在のクエリパラメーターはforEach
を使うと内部のgeneratorがvalue, key
を引数としてループを回します。
現在のクエリパラメーターのペアを維持しつつ、新しいクエリパラメーターに置き換えていきます。
history.replaceState
HTML5から実装されたAPIで、現在の履歴(=URL)を操作できます。
似たAPIとしてpushState
がありますが、これを利用すると履歴が増えていく違いがあります。