[Next.js] Hook 반환 값에 undefined가 포함되는 이유

정다롱·2024년 10월 24일

내일배움캠프 TIL

목록 보기
34/39

💥 React Hook의 반환값에 undefined가 포함되는 이유

현재 로그인한 사용자가 해당 게시글에 좋아요를 눌렀는지 여부를 파악하기 위해 클라이언트 컴포넌트에서 훅으로 getSession 요청을 했다.

  // LikeButton.tsx
  // 지금 로그인한 유저 정보
  const { data: user } = useSession();
  // 현재 포스트에 좋아요를 누른 유저
  const { data: likes } = usePostLikers(postId);
  // 좋아요 누른 유저 목록에 유저가 있으면 true 없으면 false
  const isLike = likes?.some((post) => post.like_user === user?.id) || false;
  // 좋아요 낙관적 업데이트 하는 뮤테이션 불러오기
  const likeButtonHandler = useToggleLikeButton(user, postId, isLike);

그런데 뮤테이션을 호출할 때 user에서 타입 오류가 발생했다.

분명 fetch 함수에서도 null, User만 반환하고 있고 useSession Query에서도 명시적으로 User||null 타입을 반환하고 있는데 const { data: user } = useSession(); 해당 부분의 user 가 User, null, undefined 세가지 타입을 모두 포함하고 있었다.

// 세션 정보 가져오는 함수
export const fetchSessionData = async () => {
  const { data, error } = await browserClient.auth.getSession();

  if (error) {
    console.error("Session fetch error:", error);
    return null;
  }

  // session이 없는 것은 정상적인 상태일 수 있음
  if (!data.session) {
    return null;
  }

  return data.session.user;
};

// 커스텀 훅 useQuery
export const useSession = () => {
  return useQuery<User | null>({
    queryKey: ["user", "session"],
    queryFn: () => fetchSessionData(),
  });
};

그런데 왜 undefined가 나오는 걸까?


✅ useSession이 비동기 요청이기 때문

useSession은 비동기 적으로 데이터를 가져오고 있기 때문에 컴포넌트가 렌더링 될 때 user값이 로드되지 않았을 수 있기 때문이다.

그래서 session 데이터를 가져오는 요청이 완료되기 전까지 user가 없으니까 자동으로 undefined가 되는 것이었다.


🥹 그럼 어덕하라고 훅은 조건문 아래에서 못쓰는데 undefined 예외처리를 어떻게 하라고

그렇다. 저번에 트러블 슈팅으로 썼던 것 같은데, React Hook은 조건문 아래에서 사용할 수 없다.
그래서

  // 지금 로그인한 유저 정보
  const { data: user, isLoading, isError } = useSession();
  // 현재 포스트에 좋아요를 누른 유저

  if (isLoading || isError) {
    return;
  }

  const { data: likes } = usePostLikers(postId);
  // 좋아요 누른 유저 목록에 유저가 있으면 true 없으면 false
  const isLike = likes?.some((post) => post.like_user === user?.id) || false;
  // 좋아요 낙관적 업데이트 하는 뮤테이션 불러오기
  const likeButtonHandler = useToggleLikeButton(user, postId, isLike);

이런식으로 user 를 받아오기 전에 조건문으로 예외처리를 할 수 없다.

그럼 어떻게 해야할까!

간단하다.

그냥 초기값을 설정해주면 된다.

const { data: user = null } = useSession();
user의 초기값이 unll이라고 지정해주니 아무 문제 없이 코드가 작동되는 걸 볼 수 있다.

사실 뮤테이션 부분에서 user! 이렇게 처리할 수도 있지만 임시방편에 불과하고 나는 좀 더 근본적으로? 어디서 undefined가 반환되는 건지 해결하고 싶었는데 너무 간단하고 기본적인거라 당황했다.

훅을 사용하다보면 조건문 아래에서 사용하지 못한다는 것에 사로 잡혀서 초기 값 설정하는 방법같은 걸 까먹기도 하고, 그냥 js 쓸 때는 잘 했던 걸 ts 쓸 때는 버벅이게 되는 부분이 있다.

useState 사용할 때도 초기값 안 넣으면 undefined 나오는데 그걸 까먹어서... 20분 정도 헤맸다고 생각하니 스스로가 웃기고 황당했다! 다음엔 까먹지 말길...

0개의 댓글