教程
首先,在app文件夹中创建一个ThemeWrapper.tsx[1][2]的客户端组件[3]
///ThemeWrapper.tsx
"use client";
import { ThemeProvider } from "next-themes";
import { ReactNode } from "react";
export default function ThemeWarpper({ children }: { children: ReactNode }) {
return (
//这里是因为tailwind的缘故才加这个属性,具体可以参考:https://github.com/pacocoursey/next-themes#with-tailwindcss
<ThemeProvider attribute="class">
{children}
</ThemeProvider>
);
}
然后在layout.tsx中使用这个组件
///简化的layout.tsx
import ThemeWarpper from "./ThemeWarpper";
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html>
<body>
<ThemeWarpper>{children}</ThemeWarpper>
</body>
</html>
);
}
然后在全局的css中定义黑暗模式的样式
/* 简化的globals.css */
:root {
/* Your default theme */
--background: white;
--foreground: black;
}
.dark {
--background: black;
--foreground: white;
}
然后就可以在组件中使用useTheme hook切换主题了
///Button.tsx
import { useTheme } from "next-themes";
export default function ThemeToggleButton() {
const { theme, setTheme } = useTheme();
const toggleTheme = () => {
setTheme(theme === "dark" ? "light" : "dark");
};
return (
<button onClick={toggleTheme}>
点击切换主题
</button>
);
}
参考
本文的依赖为:
- Next.js 1.5
- react 19
- typescript
- tailwind
即Next.js 1.5框架脚手架的默认选项
想要了解更多,可以访问原项目
如果对各位有帮助的话可以在GitHub Gist上给我点点
脚注
之所以不命名为ThemeProvider,是因为和next-themes的ThemeProvider命名冲突。 ↩︎
Provider设计模式参考provider-pattern。 ↩︎
后文layout.tsx是服务端组件,如果直接layout.tsx中使用next-themes的ThemeProvider(客户端组件),在测试环境可能是正常的,但是部署环境就会出些奇怪的错误,而且可能不报错,很难排查!所以一定要创建一个客户端组件然后导入。 ↩︎