next.js: (AppDir) 🙏🏻 Don't show a warning when when attributes are dynamically added to the tag before hydration

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 22.1.0: Sun Oct  9 20:15:09 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T6000
Binaries:
  Node: 16.15.1
  npm: 8.11.0
  Yarn: 1.22.19
  pnpm: 6.28.0
Relevant packages:
  next: 13.1.1
  eslint-config-next: 11.0.1
  react: 18.2.0
  react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true)

Link to the code that reproduces this issue

https://github.com/garronej/mui-next-appdir-demo/tree/darkmode

To Reproduce

git clone https://github.com/garronej/mui-next-appdir-demo
cd mui-next-appdir-demo
git checkout darkmode
yarn
yarn dev

Describe the Bug

When I dynamically add the attribute <html data-fr-theme="dark" > on client side I get the following warning:

Warning: Extra attributes from the server: data-fr-theme (more like: ‘extra argument added by the client before hydratation’)

image

(the warning is only shown in dev mode)

Expected Behavior

Not having a warning.
This html attribute decides what CSS --var colors are used.

Waiting for the hydration to add the attribute result in white flashes:

https://user-images.githubusercontent.com/6702424/209474952-bab2a037-efe6-461c-9995-35357e41a908.mov

In PagesDir there was no warning.

Same setup in Next 13 PagesDir giving no warning
git clone https://github.com/garronej/mui-next-appdir-demo
cd mui-next-appdir-demo
git checkout pagesdir-darkmode
yarn
yarn dev

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 6
  • Comments: 18 (13 by maintainers)

Most upvoted comments

Ok I’ve read of an attribute you can use to suppress hydration warning.

from the react beta docs : https://beta.reactjs.org/reference/react-dom/client/hydrateRoot#suppressing-unavoidable-hydration-mismatch-errors

If a single element’s attribute or text content is unavoidably different between the server and the client (for example, a timestamp), you may silence the hydration mismatch warning.

To silence hydration warnings on an element, add suppressHydrationWarning={true}

So to suppress it you would do :

<html suppressHydrationWarning={true}> 
   <head>
   <Script strategy="beforeInteractive" dangerouslySetInnerHTML={{
          "__html": ` 
          document.documentElement.setAttribute("data-fr-theme", "dark") 
          `
        }} />
   </head>
<body>
   {/*rest of your code*/}
</body>
</html>

Here i used the <Script> component from next/script and I added a strategy of beforeInteractive to tell next to not add a defer attribute and render it before hydration. got from the docs : https://beta.nextjs.org/docs/api-reference/components/script#beforeinteractive

@Fredkiss3 You are the real MVP ❤️!

It only work with <script /> though. <Script /> is evaluated too late, we get a white flash, even with the beforeInteractive strategy enabled.

Closing now.
Thank you very much!

One of the solutions could be to first check for dark mode media query with css @media (prefers-color-scheme: dark), that way you don’t have to run a Js script first to manage the dark mode. As for manual toggle of dark-mode it is hard since next 13 with appDir hydrate your page from the root as opposed to next 12 where it hydrated from a #__next div.

I don’t know if any solution could work