[TIL] 2022-03-26

10570 단어 TILTIL

오늘의 TIL

Self Study

  • 게시판에 댓글 기능 추가하기
    : 댓글 생성, 조회, 수정, 삭제 (+별점⭐️)

오늘은 하루종일 댓글 CRUD를 구현했다.
일단 댓글은 게시판에 속해있기 때문에 하나하나 조회하는 게 아니고 리스트 형태로 게시판의 아이디를 활용한다는 것이 게시판과 달랐다.
그리고 게시판은 List에서는 목록조회, Detail에서는 상세 조회, Write에서는 생성/수정으로 한 화면 당 기능이 한두개였던 것에 비하여, 댓글은 CRUD가 BOARD_DETAIL 화면 안에서 전부 이루어지기 때문에, 컴포넌트를 어디에서 진입하게 해야 하는지 고민이 필요했다.

export default function BoardsDetailPage() {
  const router = useRouter();
  const boardId = String(router.query.boardId);
  return (
    <>
      <BoardDetail />
      <CommentWrite />
      <Comments />
    </>
  );
}

우선 각 기능 별로 컴포넌트를 생성하고, BoardDetail의 return문에 댓글의 컴포넌트들을 전부 입력했더니 화면이 이어져서 나왔다. 짱 좋고 신기햇,,
화면을 연결하고 나서는 기존의 게시판과 비슷하게 작업을 했다.

그런데 별점이 생각보다 어려웠다!!!
일단 댓글을 생성할 때 별점을 누르면 누른 별점의 id를 setRating하고, emotion에도 눌렸는지 상태값 여부를 통해 눌린 별점의 색을 다르게 표현할 수 있어서 간단했는데,

/*CommentWrite*/
//Presenter
  const onClickStar = (e: MouseEvent<HTMLButtonElement>) => {
    if (e.target instanceof Element) {
      setRating(Number(e.target.id));
    }
  };


//Presenter
<S.CStar id="1" isStar={props.rating >= 1} onClick={props.onClickStar}>/S.CStar>
            ...
<S.CStar id="5" isStar={props.rating >= 5} onClick={props.onClickStar}>/S.CStar>


//Emotion
export const CStar = styled.button`
  background-image: ${(props: any) =>
    props.isStar
      ? "url('/boards/detail/comment/CYellowStar.png')"
      : "url('/boards/detail/comment/CGrayStar.png')"};
`;

조회할 때는 어떻게 표현을 해줘야 하나.... 참 고민이 되었다.
처음에는 삼항 연산자를 썼다가,, 조건이 너무 많아져서 if문을 쓰다가,, switch문도 써보고,,, 별점 보여주는 거 하나에 코드가 40~50줄을 넘어가고,,,, for문이나 map 안에서 setState를 쓰면 리렌더를 너무 많이 했다면서 에러가 발생했다,,ㅎㅎ 미안해 맥북아 고생햇서ㅜ
그렇게 이것저것 고치다보니까 결국 presenter에서 rating 값으로 조건문을 주는 방법을 떠올릴 수 있었고, 어마무시한 더러운 코드를 전부 지울 수 있었다. 혼자 거의 4시간? 더 넘게? 고민한 것 같은데 이런 저런 방법이 자꾸만 떠올라서 너무 재밌었다 ㅋㅋㅋㅋㅋ

	👇🏻 처음에 시도한 노가다의 흔적..ㅎㅎㅎㅎㅎ

별점을 성공하고 자신감이 붙어서 수정도 해봤는데, 수정을 하려니까 애초에 댓글을 보여줄 때(fetchComments) 수정인지 상세보기인지 구분할 필요가 있었고, 그래서 comment List 안에 listItem을 또 빼서 List는 목록을 뿌리는 map만 넣어놓고 개별 하나하나의 댓글은 ListItem에서 수정인지 조회인지 구분해서 뿌려주도록 구현했다.

export default function CommentsUI(props: ICommentsUIProps) {
  return (
    <>
      <S.CListWrapper>
        {props.data?.fetchBoardComments.map((el: any) => (
          <CommentsItemUI
            key={el._id}
            el={el}
            data={props.data}
            onClickDelete={props.onClickDelete}
          />
        ))}
      </S.CListWrapper>
    </>
  );
}

이제 수정을 눌렀을 때 기존의 입력값을 보여주는 것과 수정하고 나서 수정 화면을 다시 상세 화면으로 돌리는 것만 추가하면 완ㅋ벽ㅋ한 댓글이 완성된다! 신난다! 굿~~!

좋은 웹페이지 즐겨찾기