I am getting an error building my project on netlify (WebpackError: ReferenceError: document is not defined). In develop works fine!
I saw that is possible to solve this problem with JSDOM but i have tried and i couldn't make it right.
import React from "react";
import "../css/DarkMode.css";
const DarkMode = () => {
let clickedClass = "clicked";
const body = document.body;
const lightTheme = "light";
const darkTheme = "dark";
let theme;
if (localStorage) {
theme = localStorage.getItem("theme");
}
if (theme === lightTheme || theme === darkTheme) {
body.classList.add(theme);
} else {
body.classList.add(lightTheme);
}
const switchTheme = (e) => {
if (theme === darkTheme) {
body.classList.replace(darkTheme, lightTheme);
e.target.classList.remove(clickedClass);
localStorage.setItem("theme", "light");
theme = lightTheme;
} else {
body.classList.replace(lightTheme, darkTheme);
e.target.classList.add(clickedClass);
localStorage.setItem("theme", "dark");
theme = darkTheme;
}
};
return (
<button
className={theme === "dark" ? clickedClass : ""}
id="darkMode"
className={"btnDarkMode"}
onClick={(e) => switchTheme(e)}
></button>
);
};
export default DarkMode;
Extending @mirik999's answer:
It's not about jsdom per se. As it has been said, with React, you are creating and manipulating a virtual DOM (vDOM), and with your snippet, you are pointing directly to the real DOM (document.body and so on). In addition, these actions decreases drastically the performance of the code/application since they have a huge cost by the browser, that's why React is so fast (among other things).
Manipulating the real DOM in a React application may cause severe caveats and warnings, potentially blocking the hydration of React (the refreshing/re-rendering new content-on-demand).
The fact that your code works under gatsby develop and not in gatsby build is, summarizing, because gatsby develop is handled by the browser, where there are global objects (such as window or document). gatsby build id compiled in the Node server, where obviously there's no window or document because they are not even created yet.
The easy workaround is to wrap your code (where you are using global objects) in this condition:
if (typeof window !== `undefined`) { // or typeof document !== 'undefined'
// your code that uses global objects here
}
But as I said, it may block the hydration of React.
To add theming in Gatsby, you have a bunch of options like using plugins (gatsby-plugin-dark-mode) or use a React-based approach.
Useful resources:
You want to realize theme switching totally wrong.
useEffect() hook. ( after page init )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