How execute <Script> in every render ?
Unanswered
Fire ant posted this in #help-forum
Fire antOP
Hello, i have a basic Script for the light and dark mode :
<head>
<Script id="theme-init" strategy="beforeInteractive">
{`
try {
const stored = localStorage.getItem('theme');
if (stored === 'dark' || stored === 'light') {
document.documentElement.setAttribute('data-theme', stored);
document.cookie = 'theme=' + stored + '; Path=/; Max-Age=31536000; SameSite=Lax';
}
} catch (e) {}
`}
</Script>
</head>, the problem is here : when i use <Link> component, this script is not executed, so the dark-mode / light mode do not persist when i change the page. Do you have an idea how to deal with it ? Thanks.8 Replies
Fire antOP
I should point out that the pages generated by this layout.tsx are made with SSG, so i can't use cookies.
Cinnamon Teal
Is there a reason you are going with your own implementation instead of using
If there is no specific reason I would use a library like that for this as it handles everything fine.
Pretty sure they also use a similar technique to yours where they execute a script just before hydration happens on the client.
next-themes? https://www.npmjs.com/package/next-themesIf there is no specific reason I would use a library like that for this as it handles everything fine.
Pretty sure they also use a similar technique to yours where they execute a script just before hydration happens on the client.
Fire antOP
In my case, implementing a dark/light mode is very simple; I assumed I didn't need an external library for such a small task. But looking at the package contents, it seems like you're using a custom React hook to implement it. So, why not do the same thing instead of using a
<script>?Cinnamon Teal
Yeah, I agree I would also try to implement it by self instead of adding another package.
But this is one place I personally have realized it gives better DX instead of me trying to implement it by myself. That's why I just wanted to mention that library here.
But this is one place I personally have realized it gives better DX instead of me trying to implement it by myself. That's why I just wanted to mention that library here.
it seems like you're using a custom React hook to implement it. So, why not do the same thing instead of using a <script>?Not sure whether I understood your question correctly. But that library also executes a script before hydration happens but it's just that we don't have to worry about that part. I don't think there is another way to properly pick the correct theme on a server rendered page without having a flicker otherwise. And then it gives us a hook to read and write values.
Fire antOP
I tested next-themes, it's working. I'm quite curious to know how the script is executed each time before hydration.
@Fire ant I tested next-themes, it's working. I'm quite curious to know how the script is executed each time before hydration.
Cinnamon Teal
I haven't looked deep into it, but I don't think the script gets executed on client navigation, if that's what you meant.
It will only execute once for the initial render on the client.
Looks like this is the part where the script is injected into the HTML head: https://github.com/pacocoursey/next-themes/blob/main/next-themes/src/index.tsx#L212-L217
So I think what happens is, on the server when the code is executed it injects the script which is defined in https://github.com/pacocoursey/next-themes/blob/main/next-themes/src/script.ts to the HTML using the above code.
Then once the client receives that HTML and parses through the code it encounters that
It will only execute once for the initial render on the client.
Looks like this is the part where the script is injected into the HTML head: https://github.com/pacocoursey/next-themes/blob/main/next-themes/src/index.tsx#L212-L217
So I think what happens is, on the server when the code is executed it injects the script which is defined in https://github.com/pacocoursey/next-themes/blob/main/next-themes/src/script.ts to the HTML using the above code.
Then once the client receives that HTML and parses through the code it encounters that
<script> tag and executes it's code. That is before React is loaded and hydration is happened. After that on the client React takes over.Fire antOP
I might have misunderstood how 
next and this package work, but in my case, I don't understand why the script is only executed once. When I change pages using <link>, I don't see the theme that remains in the HTML, but with this package, it's there, even though we're also using a <script> tag. It's quite strange. Or perhaps there's a useEffect that triggers it every time.
Cinnamon Teal
I highly doubt the script needs to re run on client side navigation.
The whole point of that script is to quickly lookup the local storage and grab the theme value and set the class or data attributes as needed on the initial page load. So the CSS acts accordingly.
After that once React takes over you can read and write to local storage using React, so there is no need for a script tag to do that work.
The whole point of that script is to quickly lookup the local storage and grab the theme value and set the class or data attributes as needed on the initial page load. So the CSS acts accordingly.
After that once React takes over you can read and write to local storage using React, so there is no need for a script tag to do that work.