NextJS(Beta) Text content does not match server-rendered HTML

hwisaac·2023년 5월 10일
0

Next.js

목록 보기
29/29

https://nextjs.org/docs/messages/react-hydration-error

이 에러가 발생하는 이유

애플리케이션을 렌더링하는 동안, 서버 사이드 렌더링(SSR/SSG)된 React 트리와 브라우저에서 첫 렌더링 시 렌더링된 React 트리 간에 차이가 있었습니다. 첫 번째 렌더링은 ReactHydration 기능 중 하나입니다.

이러한 차이로 인해 React 트리가 DOM과 동기화되지 않아 예기치 않은 콘텐츠/속성이 나타날 수 있습니다.

해결 방법

일반적으로 이 문제는 라이브러리나 애플리케이션 코드에서, 서버 사이드 렌더링(SSR/SSG)과 브라우저에서의 렌더링 사이에 차이가 발생할 수 있는 것에 의존하고 있을 때 발생합니다. 이러한 예로는 컴포넌트 렌더링에서 window를 사용하는 것이 있습니다.

예시:

function MyComponent() {
  // 이 조건문은 `window`에 의존합니다. 브라우저의 첫 렌더링에서는 `color` 변수가 다를 수 있습니다.
  const color = typeof window !== 'undefined' ? 'red' : 'blue'
  // color가 프롭으로 전달되기 때문에 서버 측에서 렌더링된 것과 브라우저 첫 렌더링에서 렌더링된 것 간에 불일치가 발생합니다.
  return <h1 className={`title ${color}`}>Hello World!</h1>
}

해결 방법:

// 브라우저에서만 실행되는 useEffect를 사용하여 첫 번째 렌더링이 다르게 되는 것을 방지할 수 있습니다. Hydration에서 실행됩니다.
import { useEffect, useState } from 'react'
function MyComponent() {
  // 기본값은 'blue'이며, 이 값은 서버 측 렌더링과 브라우저 첫 렌더링(하이드레이션) 모두에서 사용됩니다.
  const [color, setColor] = useState('blue')
  // Hydration에서 useEffect가 호출됩니다. `window`는 `useEffect`에서 사용할 수 있습니다.
  // 이 예시에서는 window를 사용하므로 브라우저에서만 사용됩니다. window에서 무언가를 읽어야 하는 경우에는 문제 없습니다.
  // `setColor`를 호출하여 useEffect에서 렌더링을 트리거하면 하이드레이션 후 "브라우저 특정 값"이 사용 가능합니다. 이 경우에는 'red'입니다.
useEffect(() => setColor('red'), [])
// color가 상태로 전달되기 때문에 서버 측에서 렌더링된 것과 브라우저 첫 렌더링에서 렌더링된 것 간에 불일치가 발생하지 않습니다. useEffect가 실행된 후에는 color가 'red'로 설정됩니다.
return <h1 className={title ${color}}>Hello World!</h1>
}

다른 예시:

divp 태그 내부에 있으면 잘못된 HTML이므로 hydration 불일치가 발생할 수 있습니다.

export const IncorrectComponent = () => {
  return (
    <p>
      <div>
        This is not correct and should never be done because the p tag has been
        abused
      </div>
      <Image src="/vercel.svg" alt="" width="30" height="30" />
    </p>
  )
}

해결 방법:

export const CorrectComponent = () => {
  return (
    <div>
      <div>
        This is correct and should work because a div is really good for this
        task.
      </div>
      <Image src="/vercel.svg" alt="" width="30" height="30" />
    </div>
  )
}

CSS-in-JS 라이브러리의 일반적인 원인:

Local Overrides:

Chrome 개발자 도구에서 로컬 오버라이드가 활성화되어 있을 수 있습니다. 이 경우, 서버 사이드 렌더링(SSR)이 출력한 HTML과 다른 HTML이 제공됩니다. 또한 view-source에 표시되지 않기 때문에 무슨 일이 일어나고 있는지 이해하기 어려울 수 있습니다.

iOS에서의 일반적인 원인:

iOS는 텍스트 콘텐츠에서 전화번호, 이메일 주소 및 기타 데이터를 감지하여 링크로 변환하려고 합니다. 이로 인해 hydration 불일치가 발생할 수 있습니다. 이 문제는 다음 메타 태그를 사용하여 해결할 수 있습니다:

<meta name="format-detection" content="telephone=no, date=no, email=no, address=no" />

0개의 댓글