Next.js의 Pre-render를 막고 클라이언트에서만 렌더링되도록 하기

Sooo·2023년 8월 19일
1

Next.js

목록 보기
2/4

결론

  • hydration issue
  • 브라우저에서 렌더링된 html이 서버에서 렌더링된 것과 일치하지 않음
  • 실시간으로 변경될 수 있는 화면의 경우, client-side에서만 렌더링되도록 하자

문제

Warning: Text content did not match. Server: "2분 전" Client: "3분 전”

원인

Next에서 서버의 pre-render 결과와 client의 주입 시점 렌더 결과가 다를 때 발생하는 에러이다.
에러가 난 위치는 new Date()를 호출해 현재 시각과 그에 따른 시간차("n분 전")가 실시간으로 변경되므로, 렌더 시점에 따라 값에 차이가 날 수 있다.

클라이언트 컴포넌트는 클라이언트 사이드에서만 렌더링될 줄 알았는데, Next.js의 모든 페이지는 서버에서 pre-render된다고 한다.

Components in the Client Component module graph are primarily rendered on the client, but with Next.js, they can also be pre-rendered on the server and hydrated on the client.

해결

By default, Next.js pre-renders every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript. Pre-rendering can result in better performance and SEO.
(...) When a page is loaded by the browser, its JavaScript code runs and makes the page fully interactive (this process is called hydration in React).
— Next.js, Building Your Application, Rendering

두 가지 해결방법이 가능하다

#1 useEffect 안으로 옮겨서 state setting

state를 저장하는 코드를 useEffect 안에 넣으면, state가 client-side에만 저장되므로 이슈가 발생하지 않는다.

#2 next/dynamic 의 { ssr: false } 옵션 사용하기

이 컴포넌트가 사용될 때마다 서버에 포함되는 것을 막고 client-side에서만 동적으로 포함된다.

const Home = dynamic(
    () => import('../components/Home'),
    { ssr: false }
)

문제가 발생한 컴포넌트의 state 로직을 수정할 수 있으면 #1, 그렇지 못한 외부 라이브러리라면 #2를 선택할 수 있다.

위 케이스는 #1로 해결했다.

+ 추가

⚠️ 새로운 데이터를 받아왔지만 UI에 반영되지 않음

useEffect(()=>{
    const rowData = makeRows(chats, pathname, page);
    setRows(rowData);
},[chats]); 

UI를 만드는 함수를 useEffect안에 옮겨두고, 받아온 데이터를 의존성 배열에 안 넣어줘서 생긴 문제였다.

주의합시다~

0개의 댓글