[React] 댓글 리스트 뷰 & 추가, 편집, 삭제 기능구현

SangHeon·2022년 12월 28일
14

[React]

목록 보기
4/8
post-thumbnail

*Javascript로 만들었던 인스타그램 프로젝트를
React로 포팅하며 구현한 기능을 정리한 내용입니다.
상태관리 라이브러리를 사용하지 않고 작업을 진행하였습니다.

댓글 추가

Input창에 댓글을 입력하고 Enter Press or 게시버튼을 클릭하면
commentList에 새로운 댓글 데이터가 추가되어 다시 렌더링되는 구조로 작업하였습니다.

export default function WrapComments() {
  const [input, setInput] = useState('')
  const [commentList, setCommentList] = useState(data)

  const addComment = () => {
    if (input !== '') {
      const lastCmtIndex = commentLists.length - 1;
      const addedCmtId = commentLists[lastCmtIndex].id + 1;
      const newComment = {
        id: addedCmtId,
        username: 'bibigo',
        content: input,
      };
      setCommentLists([...commentLists, newComment]);
      setInput('');
    }
  };
  
  return (
    <>
      <ul className="list-cmt">
        {commentLists.map(comment => {
          const commentId = comment.id;
          return (
            <Comment
              key={commentId}
              comment={comment}
            />
          );
        })}
      </ul>
          
      <div className="box-inp-cmt">
        <input
          type="text"
          placeholder="댓글 달기..."
          value={input}
          onChange={e => setInput(e.target.value)}
          onKeyDown={e => (e.key === 'Enter' ? addComment() : null)}
          />
        <button className="btn-submit" disabled="" onClick={addComment}>
            게시
        </button>
      </div>
	</>
  )
}

input에 값이 입력되면 onChange의 setInput을 통해 문자열이 저장되고,
Enter Press 혹은 게시 버튼 클릭시 addComment() 함수가 실행됩니다.

미리 만들어둔 addComment() 함수 안에서 관리중인 댓글데이터의 구조대로 새로운 댓글 데이터를 만들어주고, 새로운 데이터를 commentList에 넣어주어 다시 렌더링 하는 방법입니다.

mockData를 활용하였기에 ID로 넣어주어야할 LastIndex값은 단순하게 마지막 ID값에서 +1하여 처리하였습니다.

댓글 편집

댓글 컴포넌트의 구조는 다음과 같습니다.
<WrapComments /> -> <CommentList /> -> <Comment />

<WrapComments /> 

<CommentList /> 

<Comment /> 

현재 댓글 데이터의 구조는 하나의 객체 안에 { id, username, content } 가 들어있는 상태입니다.
로그인 환경을 제외하고 댓글을 편집하기위해서는 다음과 같은 로직을 따르는데


  1. Edit 버튼을 누른다. (Enter Press 동일)
  2. isEditing이 true가 되어 handleEditInput() 함수가 실행되고, 상위컴포넌트에서 전달해준 editComment()안에 인자값으로 'comment id' 값과 'editvalue'값을 넣어주며 실행된다.
    (editValue의 초기값은 댓글의 content값입니다)
  3. 상위 컴포넌트의 editComment() 로직이 돌며 map으로 새로 반환된 댓글리스트를 setCommentList를 통해 state 업데이트를 해준다.
  4. state가 업데이트 되었으므로 commentList가 새롭게
    <CommentList commentList={commentList} /> 컴포넌트로 전달되고, UI를 다시 그리게 됨으로 편집된 댓글내용이 화면에 나타나게 됩니다.

요약하면
Comment 컴포넌트의 버튼을 클릭함으로 댓글 수정 input창이 나타나고,
수정이 완료된 뒤 Enter Press 혹은 버튼 클릭으로
상위에 있는 editComment() 를 실행하게 되고,

전달된 editValue값으로 선택한 댓글의 content가 변경되어 commentList의 state변경이 일어나게 됨으로, 댓글 리스트를 재 렌더링 시켜주어
수정된 댓글이 화면에 나타나게 됩니다.

댓글 삭제

삭제 기능 또한 편집과 동일한 로직을 따르게 되는데

상위 컴포넌트에서 전달해준 삭제기능을
<Comment /> 컴포넌트에서 받아 comment의 id 값만 전달해줍니다.

// 상위 컴포넌트(<WrapComments />)의 삭제 기능
const deleteComment = commentId => {
  let newCommentLists = commentLists.filter(item => item.id !== commentId);
  setCommentLists(newCommentLists);
};


// 댓글 컴포넌트(<Comment />)
export default function Comment({ comment, deleteComment }){
  
  const handleDeleteBtn = e => {
    deleteComment(comment.id);
  };

  return (
    <button className="btn-remove" onClick={handleDeleteBtn}>
      <i className="fa fa-thin fa-xmark" />
    </button>
  )

}

결과적으로 <Comment /> 컴포넌트의 handleDeleteBtn() 이 실행되면 상위에 있는 deleteComment() 함수가 실행되고,
filtering 되어진 새로운 댓글 리스트로 -> commentList의 상태값이 업데이트 됨으로 <CommentList /> 컴포넌트를 다시 그리게 되어 삭제된 댓글을 제외한 나머지 댓글들이 화면에 나타나게 됩니다.

profile
Front-end Developer

8개의 댓글

comment-user-thumbnail
2022년 12월 29일

코드 너무 너무 좋아용 최고최고!!!!!!

1개의 답글
comment-user-thumbnail
2022년 12월 29일

코드가 정말 깔끔하군요! 마치 지코의 새삥같습니다! 최고최고!!!!!!

1개의 답글
comment-user-thumbnail
2023년 1월 3일

반갑습니다. 저도 프로그램에 관심이 많습니다. 아직 많이 부족합니다. 많은 도움 부탁드립니다.

1개의 답글