🍇
Next.jsでページリロード時にクエリパラメータを自動削除するカスタムフック
Next.js v13以降でページリロード時に特定のクエリパラメータを自動的に削除するカスタムフックです。
以下のような場合に使用できると思います。
- 検索結果ページで
?q=検索ワード
というクエリパラメータを使用 - ユーザーがページをリロード
- リロード後も同じ検索結果が表示され続ける
useReloadQueryCleaner
こちらのカスタムフックを使用することで実現可能です。
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useEffect } from "react";
type PropsType = {
/** 削除したいクエリパラメータの配列 */
paramsToRemove?: string[];
/** すべてのクエリパラメータを削除するかどうか */
removeAll?: boolean;
/** クリーニング後に実行するコールバック */
onClean?: (() => void) | null;
};
/**
* ページリロード時に指定したクエリパラメータを削除する高度なカスタムフック
* - パフォーマンス最適化
* - SSR対応
* @param options - 設定オプション
*/
export const useReloadQueryCleaner = ({
paramsToRemove = [],
removeAll = false,
onClean = null,
}: PropsType = {}): void => {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
// SSR時は実行しない
if (typeof window === "undefined") return;
// リロードフラグの確認
const reloadFlag = sessionStorage.getItem("pageReloadFlag");
if (reloadFlag === "true") {
// リロードフラグをリセット
sessionStorage.removeItem("pageReloadFlag");
let shouldClean = false;
const newSearchParams = new URLSearchParams(searchParams.toString());
if (removeAll) {
// すべてのクエリパラメータを削除
shouldClean = newSearchParams.toString().length > 0;
newSearchParams.forEach((_, key) => {
newSearchParams.delete(key);
});
} else {
// 指定したパラメータのみ削除
for (const param of paramsToRemove) {
if (newSearchParams.has(param)) {
newSearchParams.delete(param);
shouldClean = true;
}
}
}
if (shouldClean) {
// URLを更新
const newUrl = newSearchParams.toString()
? `${pathname}?${newSearchParams.toString()}`
: pathname;
router.replace(newUrl);
if (typeof onClean === "function") {
onClean();
}
}
}
// リロード検出用のイベントリスナー
const handleBeforeUnload = (): void => {
sessionStorage.setItem("pageReloadFlag", "true");
};
window.addEventListener("beforeunload", handleBeforeUnload);
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
};
}, [pathname, searchParams, paramsToRemove, removeAll, onClean, router]);
};
基本的な使い方
import { useReloadQueryCleaner } from '@/hooks/useReloadQueryCleaner'
const SearchPage = () => {
// ページリロード時に 'q' パラメータを削除
useReloadQueryCleaner({
paramsToRemove: ['q']
})
return (
<div>
{/* ページのコンテンツ */}
</div>
)
}
これだけで、ページがリロードされたときに q
パラメータが自動的に削除されます。
より実践的な使用例
1. 検索フォームとの組み合わせ
const SearchPage = () => {
const [searchQuery, setSearchQuery] = useState('')
// 検索クエリとページネーションのパラメータを削除
useReloadQueryCleaner({
paramsToRemove: ['q', 'page']
})
const handleSearch = (query: string) => {
setSearchQuery(query)
router.push({
pathname: '/search',
query: { q: query }
})
}
return (
<div>
<input
value={searchQuery}
onChange={(e) => handleSearch(e.target.value)}
placeholder="検索..."
/>
</div>
)
}
高度な使用方法
すべてのクエリパラメータを削除する
const CleanPage = () => {
// すべてのクエリパラメータを削除
useReloadQueryCleaner({
removeAll: true
})
return (
<div>
{/* ページのコンテンツ */}
</div>
)
}
クリーンアップ後の処理を追加する
const AnalyticsPage = () => {
useReloadQueryCleaner({
paramsToRemove: ['utm_source'],
onClean: () => {
// クエリパラメータ削除後に実行したい処理
console.log('クエリパラメータが削除されました')
}
})
return (
<div>
{/* ページのコンテンツ */}
</div>
)
}
ぜひ、活用してみてください!
Discussion