When I use the <Link>
tag in NextJs to navigate between pages it doesn't rerun my scripts after changing pages. It only runs the scripts after the first page load or when I press reload. When using plain <a>
tags instead, it works fine because the page reloads after each navigation. As far as I can tell this happens because the <Link>
tag makes it a Single-Page Application and doesn't refresh the page when navigating between pages.
I would greatly appreciate anyway to have it rerun the scripts when navigating between pages or to have it refresh the page without using just plain <a>
tags and losing the Single-Page Application functionality.
This code doesn't refresh the page
<Link href="/page1">
<a>Page 1</a>
</Link>
<Link href="/page2">
<a>Page 2 </a>
</Link>
This code does refresh the page
<a href="/page1">Page 1</a>
<a href="/page2">Page 2 </a>
I load in all my scripts using a scripts component
export default const MyScripts = () => {
return (
<Script
strategy="afterInteractive"
type="module"
src="/scripts/myScript.js"
onReady={() => {
console.log("Ready")
}}
/>
)
}
One thing I've noticed is that the above onReady
function fires each time I change pages. Maybe someone knows how to run the myScript.js
from the onReady
.
Caution: The hack of using
history.pushState
will not work reliably, especially when DOM elements need to be fetched usingdocument.querySelector*
. Anyway, it's also better to avoid hacks if you can.
The recommended way for Next.js is to use the Script
component with the inline script.
Simply move the Javascript code from your script
tag into a Script
component. Remove the HTML script
tag and any script file as you no longer need them.
import Script from 'next/script';
// Inside your exported component:
<Script id="myScript">
// Paste the contents of /scripts/myScript.js here (and remove that file)
</Script>
Another clean way to do this is to use the useEffect
React hook. In class-based components, you can use componentDidMount
.
This idea was proposed here: samplep182's comment in: Normal scripts "" not working after page navigation · Issue #4477 · vercel/next.js
Simply move the Javascript code from your script
tag into a useEffect
block. Remove the script
tag and any script file as you no longer need them.
import { useEffect } from 'react';
// Inside your exported component:
useEffect(() => {
// Paste the contents of /scripts/myScript.js here (and remove that file)
}, []);
Notes:
It's recommended to have an empty array []
as the dependency list, to execute this on page load only.
For external scripts, please use the Script
component with the src
attribute.