我正在尝试在我的网站中使用基于 localStorage 的暗模式功能。但我在终端中遇到了 ReferenceError: localStorage is not Defined ,当我尝试控制台记录该值时,当页面第一次加载时,我得到“null”。
我添加了下面的代码。
"use client";
import { useEffect, useState } from "react";
export default function Darkmode() {
const [theme, setTheme] = useState(
localStorage.getItem("theme") ? localStorage.getItem("theme") : "light"
);
const handleTheme = (e) => {
if (e.target.checked) {
setTheme("dark");
} else {
setTheme("light");
}
};
useEffect(() => {
localStorage.setItem("theme", theme);
const localTheme = localStorage.getItem("theme");
document.querySelector("html").setAttribute("data-theme", localTheme);
}, [theme]);
console.log(localStorage.getItem("theme"));
return (
<>
// component here
</>
);
}
您面临的问题的发生是因为每个组件以及客户端组件都是在服务器上预渲染的,并且通过在
useState
调用中设置初始状态,您会遇到引用错误。这段代码应该如下所示:
"use client";
import { useCallback, useEffect, useState } from "react";
export default function DarkMode() {
const [theme, setTheme] = useState("light");
const toggleTheme = useCallback(() => {
setTheme(prev => {
// update your state via callback, this gives you the option
// to access the previous state and set the localStorage value
const nextTheme = prev === "light" ? "dark" : "light";
localStorage.setItem("theme", nextTheme);
return nextTheme;
});
}, []);
useEffect(() => {
// set the initial theme value when component mounts
// but only when the window object is defined
if (typeof window === undefined) return;
setTheme(localStorage?.getItem("theme") ?? "light");
}, []);
return <button onClick={toggleTheme}>{theme}</button>;
}
如您所见,我通过将切换主题函数包装在回调中来优化您的代码,并且仅在组件位于客户端时设置初始值。