remix icon indicating copy to clipboard operation
remix copied to clipboard

Console error - Warning: Extra attributes from the server: class

Open brightpixels opened this issue 2 years ago • 1 comments

What version of Remix are you using?

1.3.1

Steps to Reproduce

  • Generate remix app
  • Add the following to root.tsx under ScrollRestoration tag
<script
          dangerouslySetInnerHTML={{
            __html: `document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');`,
          }}
        />

Expected Behavior

To add a class to the body called 'js-enabled' without generating console errors.

Actual Behavior

It adds a class to the body call 'js-enabled' BUT it also generates the following console error

entry.client-YJ7AE2AN.js:840 Warning: Extra attributes from the server: class
    at body
    at html
    at App
    at RemixRoute (http://localhost:3000/build/_shared/chunk-KCAHDXWN.js:2523:3)
    at Routes2 (http://localhost:3000/build/_shared/chunk-KCAHDXWN.js:2506:7)
    at Router (http://localhost:3000/build/_shared/chunk-KCAHDXWN.js:734:15)
    at RemixCatchBoundary (http://localhost:3000/build/_shared/chunk-KCAHDXWN.js:1019:10)
    at RemixErrorBoundary (http://localhost:3000/build/_shared/chunk-KCAHDXWN.js:944:5)
    at RemixEntry (http://localhost:3000/build/_shared/chunk-KCAHDXWN.js:2403:12)
    at RemixBrowser (http://localhost:3000/build/_shared/chunk-KCAHDXWN.js:3116:27)
    at I18nextProvider (http://localhost:3000/build/entry.client-YJ7AE2AN.js:21838:19)

brightpixels avatar May 14 '22 21:05 brightpixels

@brightpixels try using suppressHydrationWarning as well:

<script
  suppressHydrationWarning
  dangerouslySetInnerHTML={{
    __html: `document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');`,
  }}
/>

jdnichollsc avatar Aug 11 '22 23:08 jdnichollsc

I have a different use case, but the same error.

import type { LinksFunction } from "@remix-run/node";
import { LiveReload, Outlet, Scripts } from "@remix-run/react";
import { cssBundleHref } from "@remix-run/css-bundle";

export const links: LinksFunction = () => {
  return [
    ...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []),
  ];
};

export default function App() {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <title>Remix: So great, it's funny!</title>
      </head>
      <body>
        <nav>
          <ul>
            <li>
              <a href="/">index</a>
            </li>
            <li>
              <a href="/planning">basketball planning</a>
            </li>
          </ul>
        </nav>
        <Outlet />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

image

nemonemi avatar May 25 '23 12:05 nemonemi

this seems like a legitimate hydration error to me - you're modifying the DOM between what the server sends and when react hydrates. Instead, add this class via an effect that runs after hydration.

export default function App() {
  let [jsEnabled, setJsEnabled] = React.useState(false);
  React.useEffect(() => setJsEnabled(true), []);
  return (
    <html lang="en">
      <head>{/* ... */}</head>
      <body className={jsEnabled ? "js-enabled" : ""}>{/* ... */}</body>
    </html>
  );
}

brophdawg11 avatar Aug 09 '23 19:08 brophdawg11

@nemonemi not sure how it does it but this data-gr-c-s attributes are added by your Grammarly plugin

toyflish avatar Apr 24 '24 16:04 toyflish