Reputation: 61
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;
Upvotes: 3
Views: 3425
Reputation: 389
You want to realize theme switching totally wrong.
useEffect()
hook. ( after page init )Upvotes: 1
Reputation: 29320
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:
Upvotes: 2