error일지
[Next] Warning: Prop `style` did not match. Server: "null" Client: "color:"
rachel_13
2023. 5. 5. 14:44
Link Component에 조건부 인라인 스타일링(color 값 주기)을 해줬을 때 나타는 오류이다.
Server 측에서 초기 렌더링 될 때 color 속성이 없어서 (null로 설정되어있기 때문) Client 측과 일치하지 않아 발생하는 문제.
→ Hydration Error 라고 console에서 알려주고 있다.
https://nextjs.org/docs/messages/react-hydration-error
react-hydration-error | Next.js
Text content does not match server-rendered HTML While rendering your application, there was a difference between the React tree that was pre-rendered (SSR/SSG) and the React tree that rendered during the first render in the Browser. The first render is ca
nextjs.org
대충 요약해보자면,
발생 원인
- 어플리케이션을 렌더링하는 동안 pre-rendering된 React 트리(Hydration)와 브라우저의 첫번째 렌더링 중에 rendering된 React 트리 간의 차이로 발생하였다.
- 일반적으로 이 문제는 특정 라이브러리 또는 특정 소스코드에서 pre-rendering과 브라우저 rendering 간에 다를 수 있는 항목들에 의존할 경우 발생하며, 아마도 필자의 경우 useRouter를 이용해서 pathname을 가져올 때 한번 더 렌더링되어서 component의 렌더링 과정에 차이가 발생한 것으로 추측된다.
어떻게 고쳐?
- useEffect hook 사용하기 - useEffect 는 최초에 컴포넌트들이 그려지고 난 후에 호출되기 때문에 클라이언트 사이드에서의 동작이 보장되어 있음.
- (수정전)
import { useRouter } from "next/router";
import Link from "next/link";
import styles from ".//NavBar.module.css";
export default function NavBar() {
const router = useRouter();
return (
<nav className={styles.nav}>
<Link href="/" style={{ color: router.pathname === "/" ? "blue" : "" }}>
Home
</Link>
<Link
href="/about"
style={{ color: router.pathname === "/about" ? "blue" : "" }}
>
About
</Link>
</nav>
);
}
- (수정후)
import { useRouter } from "next/router";
import Link from "next/link";
import styles from ".//NavBar.module.css";
import { useEffect } from "react";
import { useState } from "react";
export default function NavBar() {
const [color, setColor] = useState("black");
const [color2, setColor2] = useState("black");
const router = useRouter();
useEffect(() => {
if (router.pathname === "/") {
setColor("blue");
console.log("1");
}
}, [router.pathname]);
useEffect(() => {
if (router.pathname === "/about") {
setColor2("blue");
console.log("2");
}
}, [router.pathname]);
return (
<nav className={styles.nav}>
<Link href="/" style={{ color: color }}>
Home
</Link>
<Link href="/about" style={{ color: color2 }}>
About
</Link>
</nav>
);
}
그런데 굳이 저렇게 effect 훅을 쓰지 않아도, inline style을 안쓰고 className에 조건 주면 해결됨.