vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.79k stars 26.95k forks source link

`suppressHydrationWarning` not working as expected for app router #58493

Open aronwoost opened 11 months ago

aronwoost commented 11 months ago

Link to the code that reproduces this issue

https://github.com/aronwoost/nextjs-suppress-warning-issue

To Reproduce

  1. npm install
  2. npm run dev
  3. Open http://localhost:3000/ in browser

Current vs. Expected behavior

Actual result: "Hello Server" is displayed
Expected result: "Hello Client" is displayed

Verify canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 20.6.0: Thu Jul  6 22:12:47 PDT 2023; root:xnu-7195.141.49.702.12~1/RELEASE_ARM64_T8101
Binaries:
  Node: 18.17.0
  npm: 9.6.7
  Yarn: 1.22.5
  pnpm: N/A
Relevant Packages:
  next: 14.1.0
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.2.2
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Not sure

Additional context

This is the code in question:

"use client";

import styles from "./page.module.css";

export default function Home() {
  let helloLabel = "";

  if (typeof window !== "undefined") {
    helloLabel = "Client";
  } else {
    helloLabel = "Server";
  }

  return (
    <main className={styles.main}>
      <h1 suppressHydrationWarning>Hello {helloLabel}</h1>
    </main>
  );
}

suppressHydrationWarning does suppress the warning, but it does also prevents re-rendering. Without the suppressHydrationWarning prop, the text is correctly displayed but (of course) the warning is printed in the devtools console.

kostalexis89 commented 11 months ago

I have the same issue. Hope we get a fix soon.

aronwoost commented 9 months ago

Issue persists with next@14.1

sergio-milu commented 8 months ago

same issue here, it would be nice to now if this is the expected behaviour on next or if it is a bug

Vsion commented 8 months ago

+1

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote šŸ‘ on the issue description or subscribe to the issue for updates. Thanks!

sebmarkbage commented 8 months ago

It's expected behavior in all React 18+.

aronwoost commented 8 months ago

Can you point to documentation/change log?

I only find this: https://react.dev/reference/react-dom/client/hydrateRoot#suppressing-unavoidable-hydration-mismatch-errors (and have been using suppressHydrationWarning for date related issues every since)

aronwoost commented 8 months ago

Also - even with React 18 - the Page Router still have the old behavior.

capaj commented 6 months ago

@sebmarkbage how come? Are you saying that putting suppressHydrationWarning changes how the JSX element renders? I would expect it only hides the warning and keeps everything else running the exact same way.

felipedeboni commented 6 months ago

Just faced this one, we have an UTC datetime, which server prints on it's local time and on browser it will render on local user's time.

Using suppressHydrationWarning prevents the datetime to display in local time and also does nothing about the hydration errors.

d3vAdv3ntur3s commented 6 months ago

Hit this also as far as I can tell... Using a build time SSG dynamic route, that renders a client side component, e.g.

blog/[id]/page.tsx - Leveraging generateStaticParams function for dynamic SSG building of the page

return (
    <>
      <h1>{blog.name}</h1>
      <div suppressHydrationWarning={true}> 
        <BlogClient {...blog} />
      </div>
    </>

_blog/[id]/client.tsx - Exports client only component BlogClient. (NOTE: tried adding the supress at the root level in the client component as quick test, even though that's client rendered, but no change either)

Next in dev mode suggests: https://nextjs.org/docs/messages/react-hydration-error#solution-3-using-suppresshydrationwarning

As discussed above in this thread, it has had no effect, the warnings persist.

aronwoost commented 6 months ago

@d3vAdv3ntur3s Be aware that suppressHydrationWarning only works one level deep and only with text content (source), so not sure if it would work with your example.

unhyif commented 6 months ago

I'm experiencing the same issue. Without suppressHydrationWarning, the output is as expected but I have the hydration error. With suppressHydrationWarning, the output isn't as expected but I have no error.

'use client';

import { updatedDateStyle } from './HouseTableUpdatedDate.css';

interface Props {
  updatedAt: number;
}

const HouseTableUpdatedDate = (props: Props) => {
  const { updatedAt } = props;

  const updatedDate = new Intl.DateTimeFormat('ko', {
    dateStyle: 'full',
    timeStyle: 'medium',
  }).format(updatedAt);

  return <p className={updatedDateStyle}>{updatedDate}</p>;
};

export default HouseTableUpdatedDate;

I'm on next 14.2.2

shaaandi commented 4 months ago

Any update here šŸ¤” - same issue and wondering if it will be fixed soon or need to do something else šŸ‘€

AlparslanAbdikoglu commented 1 month ago

I just wont use app router until the mean time

studentIvan commented 3 weeks ago

Issue still exists in 14.2.13

Edit by maintainer bot: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote šŸ‘ on the issue description or subscribe to the issue for updates. Thanks!

dimylkas commented 3 weeks ago

Same for me with <NextUIProvider themeProps={{ attribute: "class", defaultTheme: "light" }}> which is caused that, and I'm expected the error there

brianonchain commented 2 weeks ago

@sebmarkbage how come? Are you saying that putting suppressHydrationWarning changes how the JSX element renders? I would expect it only hides the warning and keeps everything else running the exact same way.

I believe it does. Using "suppressHydrationWarning" is giving me different results in the rendered DOM, it doesn't simply just suppress warnings in Chrome dev tools.