Next.js中的脚本警告

人工智能 2026-07-09

我需要帮助,我在Next.js版本16中一直收到这个脚本警告。我正在尝试使用 next-themes 来实现浅色模式和深色模式。

## Error Type
Console Error

## Error Message
Encountered a script tag while rendering React component. Scripts inside React components are never executed when rendering on the client. Consider using template tag instead (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).


    at script (<anonymous>:null:null)
    at ThemeProvider (src/components/ThemeProvider.jsx:7:10)
    at RootLayout (src\app\layout.js:23:9)

## Code Frame
  5 |
  6 | export function ThemeProvider({ children, ...props }) {
> 7 |   return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
    |          ^
  8 | }
  9 |

Next.js version: 16.2.6 (Turbopack)

这是我的 global.css,因为我正在使用 tailwind v4 来实现浅色模式和深色模式。

@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;500;600;700&display=swap');

@import "tailwindcss";

@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));

这是我的 layout.js

import { Nunito } from "next/font/google";
import { ThemeProvider } from "@/components/ThemeProvider";
import "./globals.css";

const nunito = Nunito({
  subsets: ["latin"],
  weight: ["400", "600", "700"],
});

export const metadata = {
  title: "StoryMind",
  description: "Stories & Summaries, powered by AI",
};

export default function RootLayout({ children }) {
  return (
    <html
      lang="en"
      suppressHydrationWarning
    >
      <body
        className={`${nunito.className} antialiased h-full min-h-full flex flex-col`}>
        <ThemeProvider
          attribute="data-theme"
          defaultTheme="system"
          enableSystem
          disableTransitionOnChange
        >
          {children}
          <div id="modal-root"></div>
        </ThemeProvider>
      </body>
    </html>
  );
}

这是我的 ThemeProvider

"use client";

import * as React from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes";

export function ThemeProvider({ children, ...props }) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
}

解决方案

原理是:你的服务器不知道用户选择了哪种主题(这个信息保存在他们的浏览器中)。因此服务器会猜测为“浅色模式”。但是用户的浏览器显示为“深色模式”。现在React会报错,因为服务器输出的HTML与浏览器期望的不匹配。

"use client";

import Button from "@/components/ui/Button";
import { FiSun, FiMoon } from "react-icons/fi";
import { useTheme } from "next-themes";
import { useState, useEffect } from "react";

export default function ThemeToggle() {
  const { resolvedTheme, setTheme } = useTheme();
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect
    setMounted(true);
  }, []);

  const toggleTheme = () => {
    setTheme(resolvedTheme === "light" ? "dark" : "light");
  };

  // Render a placeholder with the same size so server and client agree
  if (!mounted) {
    return (
      <div className="w-9 h-9" aria-hidden="true" />
    );
  }

  return (
    <Button
      onClick={toggleTheme}
      variant="other"
      size="text-xl"
      className="flex items-center justify-center p-2 transition-colors rounded-full w-9 h-9 hover:bg-muted"
      aria-label={`Switch to ${resolvedTheme === "light" ? "dark" : "light"} mode`}
    >
      {resolvedTheme === "light" ? (
        <FiMoon size={20} className="transition-colors text-muted-foreground hover:text-foreground" />
      ) : (
        <FiSun size={20} className="transition-colors text-muted-foreground hover:text-foreground" />
      )}
    </Button>
  );
}

修复Hydration不匹配:起初,服务器和浏览器渲染出的内容完全相同。没有不匹配。只有在页面完全加载后,才会切换到真实的图标。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章