I’m having trouble with adding className for my bar before the page loads; I succeeded in adding it for my HTML tag but failed to add it to my bar. I store my theme in localStorage and get it from ThemeLoader. I’m using Nextjs for my page.
Here is the code snip ThemeLoader:
import React from "react";
import Head from "next/head";
import { useEffect } from "react";
const ThemeLoader = ({ theme, setTheme, setThemeUse, themeProvider }) => {
useEffect(() => {
const isFirstTimeOnPage = !localStorage.getItem("userTheme");
if (isFirstTimeOnPage) {
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
.matches
? "dark"
: "light";
setTheme(systemTheme);
localStorage.setItem("userTheme", systemTheme);
setThemeUse(
systemTheme === "light" ? themeProvider[0] : themeProvider[1]
);
} else {
const savedTheme = localStorage.getItem("userTheme");
setTheme(savedTheme);
setThemeUse(savedTheme === "light" ? themeProvider[0] : themeProvider[1]);
}
const themeChangeListener = (e) => {
const newTheme = e.matches ? "dark" : "light";
setTheme(newTheme);
setThemeUse(newTheme === "light" ? themeProvider[0] : themeProvider[1]);
localStorage.setItem("userTheme", newTheme);
};
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", themeChangeListener);
return () => {
window
.matchMedia("(prefers-color-scheme: dark)")
.removeEventListener("change", themeChangeListener);
};
}, [setTheme, setThemeUse, themeProvider]);
useEffect(() => {
document.documentElement.className =
theme === "light" ? "light-theme" : "dark-theme";
}, [theme]);
return (
<Head>
<style>
{`
:root {
--background-color-light: #ffffff;
--background-color-dark: #000000;
--text-color-light: #000000;
--text-color-dark: #ffffff;
}
html.light-theme {
background-color: var(--background-color-light);
color: var(--text-color-light);
}
html.dark-theme {
background-color: var(--background-color-dark);
color: var(--text-color-dark);
}
/* Đặt theme ngay lập tức */
html {
background-color: var(--background-color-light);
color: var(--text-color-light);
transition: background-color 0.25s ease-out, color 0.25s ease-out;
}
`}
</style>
<script
dangerouslySetInnerHTML={{
__html: `
(function() {
var userTheme = localStorage.getItem('userTheme');
if (userTheme) {
document.documentElement.className = userTheme === 'dark' ? 'dark-theme' : 'light-theme';
} else {
var systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
document.documentElement.className = systemTheme === 'dark' ? 'dark-theme' : 'light-theme';
}
})();
`,
}}
/>
</Head>
);
};
export default ThemeLoader;
Here are my Bar tags and CSS:
<nav id="bar" className={"Bar--container Bar--" + theme}>
...
And CSS for changing theme:
.Bar--dark{
background: rgba(22, 22, 22, 1);
border: 1px solid hsl(0 0% 100% / 0.077);
}
.Bar--light{
background: #fefefe;
border: 1px solid rgb(0, 0, 0, 0.1);
}
I want it loaded like this when loading into website
<nav id="bar" className="Bar--container Bar--dark">
...
Thank you!
2
Answers
Here is the answer for me:
clsx is generally used to conditionally apply a given className
This syntax means that some class will only be applied if a given condition evaluates to true