[React] Text content does not match server-rendered HTML

Chanhee Kang·2022년 11월 9일
0

Front-end

목록 보기
3/3

발생이유

navbarItems을 map 을 통해 보여주기 위해, 초기에 key값을 부여하지 않은 상태로 코드를 구현하였다가, 이후 console내 log를 확인후 key값을 {index}로 부여하게끔 코드 수정후 refersh를 하였을때 적용할때 발생하였음

아래블로그에 따르면, 렌더링된 HTML(SSR, ISR 등)이 업데이트되지만 페이지 로드 후 React 코드는 업데이트되지 않을 때 발생한다고 함.

관련 블로그 글

해결 방법

Next.js에선 이를 ‘React Hydration Error’라고 명시하였는데, 해당 문서를 살펴보면, 애플리케이션을 렌더링하는 동안 사전에 렌더링된 React 트리(SSR/SSG)와 브라우저에서 랜더링된 React 트리 간에 차이가 존재하여, React 트리가 DOM과 동기화되지 않고 예기치 않은 콘텐츠/속성이 나타날 수 있다고 합니다.

일반적으로 이 문제는 사전 렌더링과 브라우저 간에 다를 수 있는 것에 의존하는 특정 라이브러리 또는 애플리케이션 코드를 사용하기 때문에 컴포넌트의 렌더링에서 window 를 사용하여 해결 할수 있다고 합니다.

아래와 같은 예제의 경우,

function MyComponent() {
  // This condition depends on `window`. During the first render of the browser the `color` variable will be different
  const color = typeof window !== 'undefined' ? 'red' : 'blue'
  // As color is passed as a prop there is a mismatch between what was rendered server-side vs what was rendered in the first render
  return <h1 className={`title ${color}`}>Hello World!</h1>
}

Next.js 에서는 아래와 같이 에러를 해결할 수 있다고 한다.

// In order to prevent the first render from being different you can use `useEffect` which is only executed in the browser and is executed during hydration
import { useEffect, useState } from 'react'
function MyComponent() {
  // The default value is 'blue', it will be used during pre-rendering and the first render in the browser (hydration)
  const [color, setColor] = useState('blue')
  // During hydration `useEffect` is called. `window` is available in `useEffect`. In this case because we know we're in the browser checking for window is not needed. If you need to read something from window that is fine.
  // By calling `setColor` in `useEffect` a render is triggered after hydrating, this causes the "browser specific" value to be available. In this case 'red'.
  useEffect(() => setColor('red'), [])
  // As color is a state passed as a prop there is no mismatch between what was rendered server-side vs what was rendered in the first render. After useEffect runs the color is set to 'red'
  return <h1 className={`title ${color}`}>Hello World!</h1>
}

0개의 댓글