[TIL]231229_supabase를 이용하여 댓글 CRUD

ㅇㅖㅈㅣ·2024년 1월 1일
2

Today I Learned

목록 보기
51/93
post-thumbnail

👩🏻‍💻 Today Learn

  • 심화프로젝트 리뷰등록 작업
  • 스탠다드반 수업

🤦🏻‍♀️ 고민한 부분

supabase를 사용하면서 typescript+next.js를 이용하여 댓글기능을 만드는건 어려움이 많았다 하하..

우선 데이터를 가져오고, 삭제하고, 업데이트하는 api는 supabase 문서에 친절하게 나와있었다.

가져오기

추가

업데이트

삭제

나의 API코드

// 리뷰 댓글 가져오기
export const fetchReviewComment = async () => {
  const fetchReviewCommentQuery = await supabase
    .from('review_comment')
    .select('*, profiles(*)')
    .returns<Tables<'review_comment'>[]>();

  const {data: fetchReviewCommentData, error} = fetchReviewCommentQuery;
  return {data: fetchReviewCommentData, error};
};

// 리뷰 댓글 추가하기
export const addReviewComment = async (userId: string, comment: string, reviewId: number) => {
  return await supabase
    .from('review_comment')
    .insert({user_id: userId, content: comment, review_id: reviewId})
    .select();
};

// 리뷰 댓글 삭제하기
export const deleteReviewComment = async (id: number) => {
  return await supabase.from('review_comment').delete().eq('id', id);
};

// 리뷰 댓글 수정하기
export const updateReviewComment = async ({id, editingComment}: {id: number; editingComment: string}) => {
  return await supabase.from('review_comment').update({content: editingComment}).eq('id', id).select();
};

리액트 쿼리로 서버상태 관리

 const {data: reviewCommentData} = useQuery({
    queryKey: ['fetchReviewCommentList'],
    queryFn: fetchReviewComment,
    refetchOnWindowFocus: false,
    staleTime: 3000,
  });

  const addCommentMutate = useMutation({
    mutationFn: async () => await addReviewComment(userId, comment, reviewId),
    onSuccess: () => {
      queryClient.invalidateQueries({queryKey: ['fetchReviewCommentList']});
    },
  });

  const deleteCommentMutate = useMutation({
    mutationFn: deleteReviewComment,
    onSuccess: () => {
      queryClient.invalidateQueries({queryKey: ['fetchReviewCommentList']});
    },
  });

  const updateCommentMutate = useMutation({
    mutationFn: updateReviewComment,
    onSuccess: () => {
      queryClient.invalidateQueries({queryKey: ['fetchReviewCommentList']});
    },
  });

여기서 쿼리키 틀리지 않게 조심하자! (대충 난 잘못써서 안됐던 경험이 있다는 뜻..)


댓글 추가하기

// 댓글 등록하기
  const commentSubmitHandler = async () => {
    if (!comment) {
      warnTopCenter({message: '댓글을 입력해주세요', timeout: 2000});
      return;
    }
    if (userId === '') {
      warnTopCenter({message: '로그인 후 댓글 작성이 가능합니다', timeout: 2000});
      return;
    }
    try {
      await addCommentMutate.mutate();
      successTopCenter({message: '댓글을 등록하였습니다', timeout: 2000});
    } catch (error) {
      console.log('reviewCommentError', error);
      errorTopCenter({message: '댓글 등록이 실패하였습니다', timeout: 2000});
    }
  };

팀원분이 toastify 훅을 만들어주셔서 한줄씩만 추가해주면 손쉽게 사용할 수 있었다.


댓글 삭제하기

// 삭제버튼 클릭
  const deleteButtonHandler = (id: number) => {
    Swal.fire({
      title: '정말로 삭제하시겠습니까?',
      text: '삭제하면 되돌릴 수 없습니다',
      icon: 'warning',
      showCancelButton: true,
      confirmButtonColor: '#83e0a5',
      cancelButtonColor: '#b0b0b0',
      confirmButtonText: 'Yes',
    }).then((result): void => {
      if (result.isConfirmed) {
        Swal.fire({
          title: '삭제되었습니다',
          icon: 'success',
        });
        deleteCommentMutate.mutate(id);
      } else {
        return;
      }
    });
  };

Sweet Alert2를 활용하여 confirm을 해서 그렇지 사실 핵심은 else윗줄 mutate부분이다.


수정하기

수정하는 부분을 가장 헤맸다 ㅠㅠ
우선 수정을 클릭하기 전에는 수정 | 삭제 형태였다가 수정을 클릭하면 취소 | 완료 상태로 바꾸는 조건부렌더링을 사용하려다보니 조금 헤맸던것 같기도 하고..

다 해봤던 기능이지만 Typescript 이놈이 골치아팠다.

// 수정완료버튼 클릭
  const completeButtonHandler = async (id: number) => {
    if (editingComment === currentComment) {
      warnTopCenter({message: '변경된 내용이 없습니다', timeout: 2000});
      return;
    }
    try {
      await updateCommentMutate.mutate({id, editingComment});
      setEditingComment(editingComment);
      setIsEdit(!isEdit);
      successTopCenter({message: '수정이 완료되었습니다', timeout: 2000});
    } catch (error) {
      console.log('updateCommentError', error);
      errorTopCenter({message: '댓글 수정이 실패하였습니다', timeout: 2000});
    }
  };

수정된 부분이 없을 시에 알려주고 수정된 부분이 있으면 바로 update가 완료되는것도 확인하였다.


✍🏻 회고

CRUD는 가장 기본적인 기능인데 왜 늘 할때마다 새로운지... 이전에 했던 코드를 보면서 해보려고 하는데 '내가 짠건데 이걸 어떻게 했었지?' 하는 생각과 함께 다시 분석하고 적용하는것에 시간이 꽤 많이 걸린다.
뭐 역시나 반복만이 답이겠지

profile
웰씽킹_나는 경쟁력을 갖춘 FE개발자로 성장할 것이다.

0개의 댓글