这是我的代码,我想为切换主题编写一个上下文提供程序。 自定义主题提供者:
'use client'
import React, {createContext, useState} from "react";
type ThemeContextType = {
theme: string;
toggleTheme: () => void;
};
export const ThemeContext = createContext<ThemeContextType>({
theme: 'light',
toggleTheme: () => {}
});
export default function CustomThemeProvider({children}: Readonly<{
children: React.ReactNode;
}>) {
const initialTheme = window.localStorage.getItem('theme') === null ? 'light' : String(window.localStorage.getItem('theme'))
const [theme, setTheme] = useState(initialTheme);
const toggleTheme = () => {
const newTheme = theme === 'dark' ? 'light' : 'dark';
window.localStorage.setItem('theme', newTheme);
setTheme(newTheme);
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
布局内容:
'use client'
import React, {useContext} from "react";
import {ThemeContext} from "@/app/CustomThemeProvider";
import Footer from "@/app/components/Footer";
import Navigation from "@/app/components/Navigation";
export default function LayoutContent({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const {theme, toggleTheme} = useContext(ThemeContext);
return (
<html lang="en" className={theme}>
<body>
<div id="layout" className="layout flex-col flex min-h-screen bg-skin-base">
<Navigation themeToggleHandler={toggleTheme}/>
<div className="flex-1">
{children}
</div>
<div>
<Footer/>
</div>
</div>
</body>
</html>
);
}
我尝试修改它。第一次尝试:
let initialTheme = 'light';
if (typeof window !== "undefined") {
initialTheme = window.localStorage.getItem('theme') === null ? 'light' : String(window.localStorage.getItem('theme'))
}
const \[theme, setTheme\] = useState(initialTheme);
第二次尝试: useEffect(),但它有切换延迟。 你能帮我吗,谢谢!
没有错误,并且切换主题流畅。
如果你想避免闪光,你可以只使用 CSS 来实现深色主题样式 - 我可以看到你正在使用 tailwind,它有一个方便的
dark:
修饰符。然后,您可以将脚本添加到 public
目录并直接使用 <script>
标签引用它,因为它不会与应用程序的其余部分捆绑在一起:https://tailwindcss.com/docs/dark-mode #支持系统首选项和手动选择。只要将标签放置在实际页面内容之上,就不会导致闪烁,因为它将在文档的其余部分之前首先被解析。请注意,您将不再需要提供程序,因为所有样式都将依赖于 CSS。每当您想要更新主题时,只需更改 <html>
标签上的类并更新 localStorage
。
或者,您可以使用服务器组件,并使用 cookie。您可以将初始值作为 prop 传递给提供者,而不是从
localStorage
获取它。 https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#using-context-providers https://nextjs.org/docs/app/api-reference/functions/饼干