You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next13中<Script/>更新html className的Hydration错误与深色模式闪烁问题

解决Tailwind暗黑模式闪烁与Hydration警告问题

一、彻底消除页面闪烁问题

用useEffect或afterInteractive脚本都会因执行时机滞后导致闪烁,最优解法是在_document.tsx(或_document.js)中添加同步内联脚本,让代码在页面DOM渲染前就读取localStorage并设置html的className:

// pages/_document.tsx
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        {/* 同步脚本,页面渲染前执行 */}
        <script dangerouslySetInnerHTML={{
          __html: `
            if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
              document.documentElement.classList.add('dark')
            } else {
              document.documentElement.classList.remove('dark')
            }
          `
        }} />
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

该脚本会在浏览器解析页面内容前运行,直接为html标签加上dark类,从根源避免闪烁问题。

二、禁用特定元素的Hydration警告

若需保留原有实现并屏蔽Hydration警告,可直接在服务端与客户端内容可能不匹配的元素上添加suppressHydrationWarning属性:

// 在html根元素上添加
<Html suppressHydrationWarning>
  {/* ... */}
</Html>

// 或在具体不匹配的元素上添加
<div suppressHydrationWarning className={isDark ? 'dark' : ''}>
  {/* ... */}
</div>

这个属性会告知Next.js忽略该元素的Hydration一致性检查,开发模式下就不会再弹出相关错误。需要注意的是,suppressHydrationWarning仅作用于单个元素,无法传递给子元素,需加在最外层存在不匹配的节点上。

另外,使用beforeInteractive脚本时出现开发模式Hydration错误,本质是服务端渲染的html无dark类,但客户端脚本提前添加导致DOM不匹配。上述_document内联脚本方案已从根源规避了这个问题——服务端渲染的html虽无dark类,但客户端脚本在DOM渲染前就完成了类的添加,不会触发Hydration不匹配。

内容的提问来源于stack exchange,提问作者Kacper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 03:19:53