[React] 인스타그램 메인페이지 댓글 기능 구현

양갱장군·2020년 10월 13일
1

TIL

목록 보기
17/39

✅ Result: setState & Event 영역

class Main extends React.Component {
  constructor() {
    super();
    this.state = {
      content: "",
      commentList: [{idx: 20201012, userId: "minnotming_", comment: "더 올려주세요ㅠ"}],
    };
  }
  
    handleChange = (e) => {
    this.setState({
      content: e.target.value
    });
  }

  addComment = () => {
    this.setState({
      commentList: [...this.state.commentList, {idx: Date.now(), userId: "jjburi_", comment: this.state.content}],
      content: ""
    })
  };
  
  handleKeyEvent = (e) => {
    if(e.key === "Enter") {
      this.addComment();
    }
  }

⏩ this.state

content는 새롭게 입력될 댓글을 받아올 property이다. 실제로 댓글란에 추가되는 기능은 commentListcomment property를 통해 render될 예정이다.

⏩ handleChange

댓글 인풋 창에 변화가 발생하면(onChange) 실행되는 함수이다. this.setState를 통해 content property의 값을 입력값으로 변화시켜준다.

⏩ addComment

게시 버튼을 누르면 실행되는 함수이다.
1) thos.setState로 content의 값은 clear해주고, commentList에는 새로운 배열을 추가해준다.
2) 이 새로운 배열 추가에는 Spread 연산자를 이용했다. push()를 통해서도 추가할 수 있지만, 이후 화면에 render할 때 문제가 발생할 수 있어 지양하는 것이 좋다고 한다. 처음엔 concat함수를 사용했으나 spread 연산자가 더 간단한 것 같아 호다닥.. 수정했다.

✨ Spread 연산자 ✨

전개 구문을 사용하면 배열이나 문자열과 같이 반복 가능한 문자를 0개 이상의 인수 (함수로 호출할 경우) 또는 요소 (배열 리터럴의 경우)로 확장하여, 0개 이상의 키-값의 쌍으로 객체로 확장시킬 수 있다.
[예시]

var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2]; // arr1 은 이제 [0, 1, 2, 3, 4, 5]

Reference: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Spread_syntax

⏩ handleKeyEvent

댓글 인풋 창에 키 이벤트가 발생하면(onKeyUp) 실행되는 함수이다.
입력된 key의 값이 "Enter"인 경우에만 addComment 함수를 실행시킨다.

✅ Result: render 영역

<div className="comment">
	<p>
		<b>jjburi_</b>베이비나카
	</p>
    	<div className="comment_wrapper">
        	{this.state.commentList.map(item =>
            	<AddComment
                userId={item.userId}
                comment={item.comment}
                idx={item.idx}
                handleRemove={this.handleRemove}
                key={item.idx}>
                </AddComment>)}
        </div>
        </div>
        	<div className="time">
            	<p>21분 전</p>
</div>
 ...
<div className="new_comment">
	<input
      className="write_newComment"
      onChange={this.handleChange}
      onKeyUp={this.handleKeyEvent}
      type="text"
      placeholder="댓글달기..."
      value={this.state.content}
      size="50"
	/>
    <button className="upload_button" onClick={this.addComment} style={{color: activeBtn? "#0095f6":"#c4e6fd"}}>
		<b>게시</b>
    </button>
</div>

⏩ this.state.commentList.map

  • 위에서 받아온 데이터를 map 함수를 활용하여 데이터 배열을 컴포넌트 배열로 변환할 수 있다.

  • map함수를 통해 commentList 배열에 있는 객체'{}'들을 순차적으로 Addcomment component의 props로 return해준다.

✨각 list의 고유한 key값을 부여해주지 않으면 개발자도구에서 warning이 발생한다. 혹시모를 에러를 미연에 방지하기 위해, 가장 유닠하고 고유해보이는 현재시간(Date.now())를 인덱스 값으로 부여해줬다. ✨

✅ Result: AddComment Component

class AddComment extends React.Component {
  render() {
    const {userId,comment,idx,handleRemove} = this.props
    return (
      <ul className="previous_comment">
        <li>              
          <span>{userId}
            <span>{comment}</span>
          </span>
          <img
            className="comment_likebutton"
            alt=""
            src="https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/bearu/heart.png"
          />
          <img id={idx}
            className="comment_deletebutton"
            onClick={handleRemove}
            alt=""
            src="https://icons-for-free.com/iconfiles/png/512/cross+delete+icon-1320196393721642367.png"
          />
        </li>
      </ul>
    )
  }
}

⏩ const {} = this.props

  • Object destructuring
    this.props에 담겨있는 값에 대해서 매번 this.props.xxx, this.props.yyy, this.props.zzz 으로 접근하는 것이 번거롭기 때문에, const { xxx, yyy, zzz } = this.props의 형태로 간단히 기술할 수 있다.

⏩ this.props.xxx

부모 component에서 생성한 props를 통해 넘겨받은 값이다. 이러한 방식으로 props를 통해 부모 컴포넌트 내부의 state 값을 자식 컴포넌트에게 전달할 수 있다.

0개의 댓글