Next.js 13에서 Error: There was an error while hydrating this Suspense boundary. Switched to client rendering
- 웹 사이트내에서 useEffect, useState를 사용하는 페이지에서 출력되는 Error
- 콘솔창에서 useEffect, useState를 사용하는 페이지에서 출력되는 Error
서버 HTML이 <body>에 <script>를 포함할 것으로 예상하지 않는다고 Error가 명시되고 있다.
Error: There was an error while hydrating this Suspense boundary. Switched to client rendering가 발생할 때
일반적으로 이 문제는 사전 렌더링과 브라우저 간에 다를 수 있는 항목에 의존하는 특정 라이브러리 또는 애플리케이션 코드를 사용하여 발생한다고 한다.
그에 따른 예시이다.
1. 이에 대한 예는 window구성 요소의 렌더링에서 사용하는 것이다.
수정 전 코드)
function MyComponent() {
const color = typeof window !== 'undefined' ? 'red' : 'blue'
return <h1 className={`title ${color}`}>Hello World!</h1>
}
- L2의 color는 'window'에 따라 달라진다.
- 브라우저의 첫 번째 렌더링 중에 'color' 변수가 다르게 할당된다.
- color가 prop으로 전달되면 서버 측에서 렌더링한 것과 첫 번째 렌더링에서 렌더링한 것이 일치하지 않는다.
수정 후 코드)
import { useEffect, useState } from 'react'
function MyComponent() {
const [color, setColor] = useState('blue')
useEffect(() => setColor('red'), [])
return <h1 className={`title ${color}`}>Hello World!</h1>
}
- 첫 번째 렌더가 다른 것을 방지하기 위해 브라우저에서만 실행된다.
- hydration 중에 실행되는 "useEffect"를 사용할 수 있다.
- L3: 기본값은 'blue'이며, 사전 렌더링 시 사용되며 브라우저에서 첫 번째 렌더링(hydration)이 수행된다.
- L4: hydration중에 'useEffect'를 호출한다.
- "window"는 "useEffect"에서 사용할 수 있다.
- 이 경우 브라우저에서 창을 확인할 필요가 없다.
- 만약 당신이 window에서 무언가를 읽을 필요가 있다면 그것은 괜찮다.
- "useEffect"에서 "setColor"를 호출하면 hydration 후 렌더가 트리거되어 "브라우저 고유" 값을 사용할 수 있게 된다.
- 이 color는 경우 '빨간색'이 된다.
- color는 prop으로 전달된 상태이므로 서버 측에서 렌더링한 것과 첫 번째 렌더링에서 렌더링한 것 사이에 불일치가 없다.
- useEffect 실행 후 색상이 '빨간색'으로 설정된다.
2. 유효하지 않은 HTML, p 내부의 div와 같은 hydration 불일치를 유발할 수 있다. 쉽게 말해 <p> 태그 안에 <div> 태그가 있으면 안된다는 것이다.
수정 전 코드)
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>
)
}
- <p> 태그 안에 <div> 태그가 존재하고 있다.
수정 후 코드)
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>
)
}
- <p>를 <div>로 바꾸어 해결했다.
3. 이번에 next.js 13을 하면서 발생한 Error
수정 전 코드)
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
</body>
</html>
);
}
- app/layout에 위치하는 layout.tsx파일에서 안에 바로 {children}이 선언되어있다.
- 위 콘솔에서 명시된 서버 HTML이 <body>에 <script>를 포함할 것으로 예상하지 않는다고 Error가 명시되고 있다.
- 이 때문에 <body>안에 {children}이 <script>를 포함하지 않더라도 useEffect()나 useState()같은 client-side에서 시행되는 로직이 <script>로 인식된다.
수정 후 코드)
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<div>{children}</div>
</body>
</html>
);
}
- {children}을 <div>로 감싸주어 해결할 수 있다.
'개발 프레임워크 > Next.js' 카테고리의 다른 글
[React, Next.js] useEffect를 사용해서 컴포넌트가 사라질 때 코드실행 (0) | 2023.03.17 |
---|---|
[React, Next.js] useEffect라는 Hook을 사용해서 렌더링 후 코드실행 (0) | 2023.03.17 |
[Next.js] 개발환경 구축 및 Next.js 13으로 업데이트 (0) | 2023.03.04 |
[React, Next.js] 모달(Modal) 구현_2 (recoil을 통한 제어) (0) | 2023.02.22 |
[React, Next.js] 모달(Modal) 구현_1 (react-modal을 통한 생성) (0) | 2023.02.22 |
댓글