React 댓글 기능 프로세스

최재홍·2022년 7월 11일
0

과제로 주어진 댓글 기능에 필요한 요건은 다음과 같았다.

  1. 사용자가 댓글 입력 후 enter를 누르거나 '게시' 버튼을 클릭 했을 때 댓글이 추가되도록 구현
  2. 생성 되는 댓글마다 컴포넌트화 시킬 것

우선 댓글이 게시되도록 해보자.

댓글이 게시되기 위한 프로세스는 다음과 같다.
리액트 환경에서 기능을 구현하기 위해서는 상하위 컴포넌트 간에 이동을 해야하는 경우가 생기므로, 기능 구현 과정의 역순으로 생각해보자.

  1. 실제로 브라우저에 댓글을 생성하는 함수 정의
  2. 컴포넌트화 된 댓글들이 변화시킬 state에 대한 정의
  3. 생성될 개별적 댓글의 컴포넌트화 과정을 정의
  4. 브라우저에 랜더링 될 댓글의 형태를 컴포넌트로 정의
  5. 특정한 조건에 의해 활성화 될 버튼에 prop을 부여
  6. 버튼을 활성화시키도록 부여될 prop의 조건에 대한 정의

 


1. 실제로 브라우저에 댓글을 생성하는 함수 정의
2. 컴포넌트화 된 댓글들이 변화시킬 state에 대한 정의

const onSubmit = event => {
  event.preventDefault();
  if (comment === '') {
    return;
  }
  setCommentArray([...commentArray, comment]);
  setComment('');
};

지금 이 시점에서 알 수 없는 변수명이 네개가 있다.
함수를 정의하는 과정에서 차후에 필요하게 될 것이기 때문에 차후에 정의한 변수들이다. 함수를 작동시키기 위해 변해야 하는 state들을 정의한다.

const [comment, setComment] = useState('');
const [commentArray, setCommentArray] = useState([]);

comment는 문자열 데이터이고, setComment함수로 state가 변화하게 된다.
commentArray는 배열형 데이터이고, setCommentArray함수로 state가 변화하게 된다.

comment, commentArray가 props로써 활용되는 방법은 아래의 과정을 거치면서 알 수 있다.

comment와 commentArray는 (차후에 밝혀질테지만) comment는 최상위 컴포넌트에서 <input>태그의 value속성에 대한 속성값으로 state가 변하게 되고, 추가될 댓글의 형태를 정의할 컴포넌트에서 <p>에 들어갈 입력값, 즉 댓글 본문이 comment의 state가 된다고 정의된다.
그러므로 그 점에 착안하여 해석하자면 '만약 댓글 본문이 빈 문자열이면' 아무런 조치없이 함수를 빠져나오고, 그렇지 않다면 setCommentArray라는 배열의 마지막 배열로 변화된 state의 comment를 포함시키고, 현재 댓글 <input>의 입력값을 비우라는 의미가 된다.


3. 생성될 개별적 댓글의 컴포넌트화 과정을 정의

 <div class="commentPlus">
        {commentArray.map((commentItem, index) => (
          <NewComment comment={commentItem} key={index} />
        ))}
 </div>

"commentPlus"라는 빈 배열에 "commentArray"라는 배열이 들어가고 map이라는 메소드에 따라서 각각의 배열 원소에 대해서 for 반복문을 작동시키듯이 깊은 복사를 하고, 각각에 index값을 부여하게 된다.

*이부분은 map 메소드를 공부하면서 다시 한번 확인해보자.


4. 브라우저에 랜더링 될 댓글의 형태를 컴포넌트로 정의

 const NewComment = ({ comment }) => {
    return (
      <div className="replyUserDiv">
        <div className="userComment">
          <strong>allong_sio</strong>
          <p className="onSubmitComment">{comment}</p>
        </div>
        <div className="likeDelete">
          <img className="likeBtn" src="images/jaehongChoi/heart.png" alt="" />
        </div>
      </div>
    );
  };

사전에 바닐라JS로 만들면서 불필요한 <div>태그들을 많이 만들었고, 이것을 react환경에 복붙하면서 그대로 유지하고 있는 모습이다. 너무 많은 css 속성들이 부여되었기 때문에 불가피하게 구조를 유지하여 진행하였다.

'NewComment'라는 컴포넌트는 {comment}라는 prop 인자를 받아 상기와 같은 구조로 랜더링 되게 된다.


5. 특정한 조건에 의해 활성화 될 버튼에 prop을 부여
6. 버튼을 활성화시키도록 부여될 prop의 조건에 대한 정의

앞의 로그인 프로세스에서도 똑같은 과정을 다뤘지만 다시 한번 복기해보자.

변화를 감지할 <input>태그에 "onChange" prop 부여, "onChange" prop에 대한 속성값으로 "handleCommentInput" 컴포넌트 함수 부여.

const handleCommentInput = event => {
    setComment(event.target.value);
    if (!!event.target.value) {
      setIsActive(true);
    } else {
      setIsActive(false);
    }
  };

isActive의 state가 변함에 따라서 <button>태그의 "disabled" prop 활성화

#질문1) onChange = {handleCommentInput}이 아니라 onChange = {handleCommentInput()}는 왜 안 될까?

답: 로그인에서도 다뤘지만 "onChange"의 속성값으로 함수를 받는다. 함수에 대한 결과값이 아니라.

0개의 댓글