💦

DarkMode切替機能のハイドレーションミスマッチの対応策(Next.js + NextUI)

2024/04/22に公開

概要

Next.jsでNextUIのテーマ(DarkMode)切替機能を実装した際と限定していますが、

テーマ(DarkMode)切替機能を追加するとUIライブラリに関係なくブラウザのコンソールに出る警告

Warning: Extra attributes from the server: class,styleの対応策と注意点の記事になります。

テーマ(DarkMode)切替機能を追加するとブラウザに以下エラーが出力される

Edge(Chromium) console
app-index.tsx:25 
 Warning: Extra attributes from the server: class,style
    at html
    at RootLayout (Server)
    at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:74:9)
    at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:82:11)
    at NotFoundErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:76:9)
    at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11)
    at DevRootNotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/dev-root-not-found-boundary.js:33:11)
    at ReactDevOverlay (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/app/ReactDevOverlay.js:87:9)
    at HotReload (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/app/hot-reloader-client.js:321:11)
    at Router (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:207:11)
    at ErrorBoundaryHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:113:9)
    at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:160:11)
    at AppRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:577:13)
    at ServerRoot (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:112:27)
    at Root (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:117:11)

原因

サーバーとクライアントの間でハイドレーションの不一致が起こるため

今回の例では、サーバーで生成したときは無かったclass, styleがRootLayout(Server)のhtmlタグに追加されてる為。

これはDarkModeなどのテーマを切り替えるような場合、使用しているUIライブラリに関係なく起こります。

対応策

https://stackoverflow.com/questions/78239051/themeprovider-from-nextui-causing-warning-extra-attributes-from-the-server-cla

根本的な解決策はないが、エラーの抑制をする事で対応する。


https://github.com/pacocoursey/next-themes?tab=readme-ov-file#with-app:~:text=Note! If you do not add suppressHydrationWarning to your you will get warnings because updates that element. This property only applies one level deep%2C so it won't block hydration warnings on other elements.<html>next-themes


https://react.dev/reference/react-dom/client/hydrateRoot#suppressing-unavoidable-hydration-mismatch-errors

https://legacy.reactjs.org/docs/dom-elements.html#suppresshydrationwarning

実行

app/layout.tsxのhtmlタグにsuppressHydrationWarning={true}を追加します。

app/layout.tsx

// 省略

export default function RootLayout({
  // 省略
  return (
+    <html lang="ja" suppressHydrationWarning={true}>
-    <html lang="ja">
      <body className={zen.className}>
        <NextuiThemeProviders>
          <Suspense fallback={<Loading />}>{children}</Suspense>
        </NextuiThemeProviders>
      </body>
    </html>
  );
}

結果&注意点

Discussion