[Next.js] React Hydration Error

2024. 10. 21. 15:51·WEB/error

🚨 에러 발생

Unhandled Runtime Error
Error: Text content does not match server-rendered HTML.
See more info here: <https://nextjs.org/docs/messages/react-hydration-error>

 

🧨 문제 상황

공식 문서: Text content does not match server-rendered HTML

더보기
  1. Incorrect nesting of HTML tags
    1. <p> nested in another <p> tag
    2. <div> nested in a <p> tag
    3. <ul> or <ol> nested in a <p> tag
    4. Interactive Content cannot be nested (<a> nested in a <a> tag, <button> nested in a <button> tag, etc.)
  2. Using checks like typeof window !== 'undefined' in your rendering logic
  3. Using browser-only APIs like window or localStorage in your rendering logic
  4. Using time-dependent APIs such as the Date() constructor in your rendering logic
  5. Browser extensions modifying the HTML
  6. Incorrectly configured CSS-in-JS libraries
    1. Ensure your code is following our official examples
  7. Incorrectly configured Edge/CDN that attempts to modify the html response, such as Cloudflare Auto Minify

이 문제는 공식 문서에도 나와있는 데 내 경우는 3번 문제에 속한다

  • 서버에서 렌더링된 HTML과 클라이언트에서 렌더링된 HTML이 일치하지 않을 때 발생하는 에러이다
  • 나 같은 경우는 Next.js의 서버 사이드 렌더링(SSR)과 클라이언트 측의 localStorage 사이에서 발생하는 차이 때문이었다
'use client';

import { useRouter } from 'next/navigation';

import useTicketStore from '@/store/ticketStore';
import { formatDateWithDayAndTime } from '@/utils/dayjsPlugin';

import { LogoImage, LogoText } from '@/public/icons';
import GenerateQR from '@/components/atoms/qrcode/GenerateQR';
import CloseButton from '@/components/atoms/button/CloseButton';
import { useEffect, useState } from 'react';
import LoadingSpinner from '@/components/atoms/feedback/LoadingSpinner';

const Page = () => {
  const router = useRouter();
  const { ticketDetail } = useTicketStore();
  const [isHydrated, setIsHydrated] = useState(false);

  useEffect(() => {
    setIsHydrated(true);
  }, []);

  const handleClose = () => {
    router.back();
  };

  return (
    <div className="flex flex-col items-center justify-between h-screen py-[8vh]">
      <div className="flex flex-col items-center justify-center flex-grow py-4 min-h-[60vh]">
        {isHydrated ? (
          <>
            <div className="flex flex-col items-center mb-[8vh]">
              <h1 className="text-xl font-medium">
                {ticketDetail?.concertTitle}
              </h1>
              <p className="mt-2 text-lg text-gray-500">
                {formatDateWithDayAndTime(ticketDetail?.startAt || '')}
              </p>
            </div>
            <GenerateQR value={ticketDetail?.ticketUuid || 'no data'} />
          </>
        ) : (
          <LoadingSpinner />
        )}
      </div>

      <div className="flex flex-col items-center justify-between flex-grow">
        <div className="flex flex-col items-center">
          <LogoImage className="mb-3 w-11 h-11" />
          <LogoText />
        </div>

        <CloseButton onClick={handleClose} hasBorder />
      </div>
    </div>
  );
};

export default Page;
  • 위 코드에서 ticketDetail을 localStorage에서 가져오고 있는데, localStorage는 클라이언트에서만 사용할 수 있기 때문에 서버에서 렌더링될 때 localStorage를 참조할 수 없어서 Hydration Error가 발생한다

 


 

🚔 해결 방법

서버 렌더링과 클라이언트 렌더링을 일치시킨다

클라이언트에서 데이터가 로드되기 전까지 loading 상태를 표시하고 useEffect로 클라이언트에서만 ticketStore에 접근하도록 한다

Hydration 처리

  • useEffect를 사용하여 클라이언트가 서버에서 Hydration된 후에만 ticektStore에서 데이터를 가져오도록 한다
  • isHydrated라는 Zustand의 상태를 사용할 수 있는 여부를 저장하는 변수를 만든다
    • true면 Hydration 되었으니 ticketStore의 데이터를 읽어서 화면에 보여준다
    • false면 Hydration 되지 않았으니 로딩 스피너를 띄운다
반응형

'WEB > error' 카테고리의 다른 글

[TanStack Query] Type 'string[]' has no properties in common with type 'InvalidateQueryFilters'.ts(2559)  (0) 2024.11.15
[React] svgr 세팅 - Duplicate identifier 'src'.  (0) 2024.11.14
[html] svg 높이 설정 에러  (0) 2024.10.21
[yarn] yarn : 이 시스템에서 스크립트를 실행할 수 없으므로 C:\Users\user\AppData\Roaming\npm\yarn.ps1 파일을 로드할 수 없습니다. 자세한 내용은 about_Execution_Policies(https://go.microsoft.com/fwlink/?LinkID=135170)를 참조하십시오.  (0) 2024.09.13
'WEB/error' 카테고리의 다른 글
  • [TanStack Query] Type 'string[]' has no properties in common with type 'InvalidateQueryFilters'.ts(2559)
  • [React] svgr 세팅 - Duplicate identifier 'src'.
  • [html] svg 높이 설정 에러
  • [yarn] yarn : 이 시스템에서 스크립트를 실행할 수 없으므로 C:\Users\user\AppData\Roaming\npm\yarn.ps1 파일을 로드할 수 없습니다. 자세한 내용은 about_Execution_Policies(https://go.microsoft.com/fwlink/?LinkID=135170)를 참조하십시오.
올콩
올콩
콩 심은 데 콩 난다
  • 올콩
    콩스토리
    올콩
  • 전체
    오늘
    어제
    • 분류 전체보기 (140)
      • SSAFY (10)
      • Algorithm (67)
        • 이론 (5)
        • 백준 (BOJ) (61)
        • 프로그래머스 (1)
      • Language (9)
        • JavaScript (0)
        • TypeScript (0)
        • Java (9)
        • Python (0)
      • Library & Runtime (15)
        • React (13)
        • Node.js (2)
      • Framework (9)
        • 이론 (2)
        • Next.js (3)
        • Vue (4)
      • DevOps (3)
        • Git (3)
      • WEB (17)
        • HTML (9)
        • error (6)
        • etc (2)
      • Computer (5)
        • 자격증 (2)
        • tip (2)
        • etc (1)
      • CS (5)
        • Network (1)
        • Blockchain (4)
  • 블로그 메뉴

    • GitHub
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    자바
    소수
    bfs
    렌더링최적화
    Java
    html5
    vue
    알고리즘
    우선순위큐
    SSAFYcial
    DP
    kakaomap
    오블완
    Algorithm
    github
    파이썬
    해시
    백준
    블록체인
    딕셔너리
    재귀
    Error
    싸피
    Next.js
    dfs
    SSAFY
    카카오맵
    티스토리챌린지
    React
    강의
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
올콩
[Next.js] React Hydration Error
상단으로

티스토리툴바