[Next.js] Next.js Event handlers cannot be passed to client component 오류 해결 및 'use client'에 대하여

Rachaen·2023년 9월 8일
1
post-custom-banner
// src/components/Navbar.tsx
import ClickButton from './ui/ClickButton';

export default function Navbar() {
  return (
    <div>
      <ClickButton
        text='클릭'
        onClick={() => {
          console.log('hi');
        }}
      />
    </div>
  );
}
// src/components/ui/ClickButton.tsx
type Props = {
  text: string;
  onClick: () => void;
};
export default function ClickButton({ text, onClick }: Props) {
  return <button onClick={onClick}>{text}</button>;
}

에러가 떴다. 이벤트 핸들러를 클라이언트 컴포넌트의 props로 전달할 수 없다는 의미이다.

ClickButton 컴포넌트를 클라이언트 컴포넌트로 만들지 않아서 그런가 싶어 'use client'를 추가해주었다.

// src/components/ui/ClickButton.tsx
'use client';	// 추가

type Props = {
  text: string;
  onClick: () => void;
};
export default function ClickButton({ text, onClick }: Props) {
  return <button onClick={onClick}>{text}</button>;
}

그럼에도 같은 에러가 났다.

Navbar가 서버 컴포넌트로 되어있어도 이벤트 핸들러가 실행되지 않고 단순히 전달될 것이라고 생각하였다. 하지만 서버 컴포넌트에서 이벤트 핸들러를 클라이언트로 컴포넌트로 전달하는 것은 지원되지 않나보다. (당연한건가?? 모르겠다...)

유튜브: Next.js Event handlers cannot be passed to client component (FIXED)

이 유튜브도 나와 같은 상황인데 상위 컴포넌트에 'use client'를 지정하여 문제를 해결했다.
서버 컴포넌트에서 클라이언트 컴포넌트로 함수를 전달하려고 할 때, 함수는 직렬화(serializable)할 수 없기 때문에 문제가 발생한다고 말한다. 그래서 단 하나의 방법은 해당 페이지를 클라이언트 컴포넌트로 전환하는 것이라 한다. 이 유튜버도 서버 컴포넌트의 장점을 포기해야하는 건 어쩔 수 없다했다. (영상이 영어라 정확히 해석했는지는 모르겠다 ㅎㅎ)
그냥 어쩔 수 없이 상위 컴포넌트를 서버 컴포넌트에서 클라이언트 컴포넌트로 전환해야하나보구나 생각했다.

공식 문서를 살펴보자! 공식문서 - Using Client Components in Next.js

"use client"로 정의하면 하위에의 모든 컴포넌트는 자동으로 클라이언트에서 렌더링 되는 것으로 간주한다는 의미다.
그래서 상위 컴포넌트를 "use client"로 정의해주면 하위는 해줄 필요가 없다!

위 다이어그램은 'use client'가 정의되어 있지 않다면 오류가 발생할 것이라는 예시이다.
toggle.js에서 onClick과 useState를 사용할 경우 서버에서 사용할 수 없는 API이기 때문에, 'use client' 지시어가 정의되어 있지 않다면 오류가 발생할 것이다.

그래서 나도 최종적으로 Navbar에만 'use client'를 추가해주었다.

// src/components/Navbar.tsx
'use client';
import ClickButton from './ui/ClickButton';

export default function Navbar() {
  return (
    <div>
      <ClickButton
        text='클릭'
        onClick={() => {
          console.log('hi');
        }}
      />
    </div>
  );
}

서버 컴포넌트에서 클라이언트 컴포넌트로 전달할 수 없다는 것을 알기 위해 꽤 오래 걸린 느낌이다. 그래도 공식문서 정독하면서 Next.js에 대해 더 알게된 것 같아 기쁘다.
Next.js가 계속해서 업데이트된다는데 이 점도 바뀌는 날이 올까?

profile
개발을 잘하자!
post-custom-banner

0개의 댓글