⚠️ 에러 메세지

⚠️ Hydration failed because the server rendered HTML didn't match the client. 
As a result this tree will be regenerated on the client. 
This can happen if a SSR-ed Client Component used


- A server/client branch 'if (typeof window !== 'undefined')'.
- Variable input such as 'Date.now()' or 'Math.random()' which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.


It can also happen if the client has a browser extension installed 
which messes with the HTML before React loaded.

See more info here: https://nextjs.org/docs/messages/react-hydration-error

 

탭마다 고정된 레이아웃이 있어서 공용 컴포넌트로 만들어서 RootLayout에 추가했다. 그랬더니 하이드레이션 에러

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ko">
      <body className="bg-bg-primary flex flex-col text-white h-screen">
        <Provider>
          <HeaderLayout>{children}</HeaderLayout>
        </Provider>
      </body>
    </html>
  );
}

 

 

 

💡 해결

useEffect 로 클라이언트에서만 실행

서버에서 생성한 html과 리액트에서 렌더링한 DOM 트리가 서로 일치 하지 않기 때문에 생긴 에러로 첫 렌더링때 의도적으로 원하는 상태를 업데이트하지 않게 하는 방법이다.

 

HeaderLayout.tsx

 const CurrentDate = () => {
    const [nowDate, setNowDate] = React.useState<string>(
      dayjs().locale("ko").format("YYYY년 MM월 DD일 (dd)")
    );

    React.useEffect(() => {
      const interval = setInterval(() => {
        setNowDate(dayjs().locale("ko").format(`YYYY년 MM월 DD일 (dd)`));
      }, 60000);

      return () => {
        clearInterval(interval);
      };
    }, []);

    return <li className="px-10 py-3 font-medium">{nowDate}</li>;
  };
  
  return (
    <CurrentDate />
  )

 

 

그 외 다른 방법으로는 아래와 같다

 

Disabling SSR on specific components

import dynamic from 'next/dynamic'
 
const NoSSR = dynamic(() => import('../components/no-ssr'), { ssr: false })
 
export default function Page() {
  return (
    <div>
      <NoSSR />
    </div>
  )
}

 

 

Using suppressHydrationWarning

html 태그에 suppressHydrationWarning 추가

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ko" suppressHydrationWarning>
      <body className="bg-bg-primary flex flex-col text-white h-screen">
        <Provider>
          <HeaderLayout>{children}</HeaderLayout>
        </Provider>
      </body>
    </html>
  );
}

+ Recent posts