I want to load a script only on certain pages. Next.js recommends using next/script tag for it.
However, when I navigate to some different pages I can still see the script present at the end of body in HTML.

import Script from "next/script";
const Comments = () => {
return (
<div className="giscus mt-16">
<Script
src="https://giscus.app/client.js"
data-repo="GorvGoyl/Personal-Site-Gourav.io"
data-repo-id="MDEwOlJlcG9zaXRvcnkyOTAyNjQ4MTU="
data-category="Announcements"
data-category-id="DIC_kwDOEU0W784CAvcn"
data-mapping="pathname"
data-reactions-enabled="0"
data-emit-metadata="0"
data-theme="light"
data-lang="en"
crossOrigin="anonymous"
strategy="lazyOnload"
onError={(e) => {
console.error("giscus script failed to load", e);
}}
></Script>
</div>
);
};
I suspect Next.js is not cleaning up the script on route change action. How do I make sure that scripts get removed on page change?
I was facing the same problem. Only solution that works for me is to reload the page as the routeChangeStart. I also made it in a custom Hook so can be reused with ease.
import { useRouter } from "next/router";
import { useEffect } from "react";
export default function useScript(url: string) {
const router = useRouter();
useEffect(() => {
const script = document.createElement("script");
script.src = url;
script.async = true;
document.body.appendChild(script);
// Needed for cleaning residue left by the external script that can only be removed by reloading the page
const onRouterChange = (newPath: string) => {
window.location.href = router.basePath + newPath;
};
router.events.on("routeChangeStart", onRouterChange);
return () => {
router.events.off("routeChangeStart", onRouterChange);
document.body.removeChild(script);
};
}, [router, url]);
}
Just need to call useScript with url of javascript
import React from "react";
import NavBar from "../src/components/NavBar";
import useScript from "../src/hooks/useScript";
type Props = {};
const ScriptLoader = (props: Props) => {
useScript("/js/theScript.js");
return (
<>
<NavBar />
<div className="container">This is normal Page</div>
</>
);
};
export default ScriptLoader;
If you want to access property set on window object from the script its best to add setTimeout to check if that object is present or not as the loading of script might take some time, after that you can set some flag to true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With