[React] [인스타그램] 댓글 추가/삭제 - state 끌어올리기

GY·2021년 12월 19일
0

리액트

목록 보기
25/54
post-thumbnail

메인페이지 댓글 추가/ 삭제 기능 구현

메인페이지에서 컴포넌트 구성은 다음과 같다.

Feeds

Feeds는 모든 피드에 대한 데이터를 가지고 있다.
한 피드에 관련된 데이터를 각각 Feed컴포넌트에 전달해준다.

  return (
    <div className="feeds">
      {feeds && feeds.map(feed => <Feed key={uuid()} feed={feed} />)}
      <div className="feed-end" ref={feedEndRef}>
        feedEnd
      </div>
    </div>
  );

Feed

댓글 추가 삭제 기능을 구현할 함수를 정의해준다.


  const [comments, setComments] = useState(commentData);

  function deleteComment(comment) {
    const updated = comments;
    const filtered = updated.filter(com => {
      return com.id !== comment.id;
    });
    setComments(filtered);
  }

  function addComment(e) {
    e.preventDefault();
    let updated = comments;
    const newCommentVal = commentRef.current.value;
    updated = [
      ...updated,
      { id: uuid(), commentId: myId, commentText: newCommentVal },
    ];
    setComments(updated);
    commentRef.current.value = '';
  }

댓글 추가 기능

Feed

<form class="comment-input">
  <input
    type="text"
    placeholder=" 댓글 달기..."
    class="text"
    ref={commentRef}
    />
  <button onClick={addComment}>게시</button>
</form>

댓글 입력창과 버튼은 피드 컴포넌트 안에 있으므로 하위컴포넌트에 함수를 전달하지 않고 해당 컴포넌트에서 처리한다.
댓글 버튼에 addComment()함수를 등록한다.

댓글 삭제 기능

Feed컴포넌트에서 Comments로 댓글 데이터를 전달한다.

<Comments comments={comments} deleteComment={deleteComment} />

Comments

Comments는 한 피드에 달린 댓글들을 전달받았다.
Comment 컴포넌트에 각각 하나의 댓글들을 전달해준다. 이때 똑같이 deleteComment()도 전달한다.

import React from 'react';
import Comment from '../Comment/Comment';
import { v4 as uuid } from 'uuid';

function Comments({ comments, deleteComment }) {
  const commentList = comments;
  return (
    <ul class="comments">
      {commentList.map(com => (
        <Comment key={uuid()} comment={com} deleteComment={deleteComment} />
      ))}
    </ul>
  );
}

export default Comments;

Comment

Comment에서 각각의 댓글들에 달린 삭제 버튼을 클릭하면 onDelete()가 호출된다.
이 onDelete()함수는 deleteComment(Comment)를 호출하는데,
여기서 state 끌어올리기가 발생한다.

import React from 'react';
import { TiDelete } from 'react-icons/ti';

function Comment({ comment, deleteComment }) {
  const onDelete = () => {
    deleteComment(comment);
  };

  return (
    <li class="comment-container">
      <span class="comment">
        <p class="id">{comment.commentId}</p>
        <span>{comment.commentText}</span>
      </span>
      <button class="delete" onClick={onDelete}>
        <TiDelete size="15" />
      </button>
    </li>
  );
}

export default Comment;

state 끌어올리기

리액트의 데이터 흐름은 상위 컴포넌트에서 하위 컴포넌트로 전달하는 하향식이자 단방향 데이터 흐름을 따른다.
state 끌어올리기는 반대로 데이터를 끌어올리는 것인데, 공유될 상태를 소유한 컴포넌트가 진리의 원천(source of truth)가 되며, 하위 컴포넌트에서 이 상위 컴포넌트의 상태를 갱신하는 것이다.

이 state 끌어올리기를 활용하는 방법은 어렵지 않다.
상위 컴포넌트에 정의된 상태를 변경하는 함수 자체를 하위 컴포넌트에 props로 전달하고, 하위 컴포넌트에서 이 콜백함수를 호출하면 된다.
단방향 데이터 흐름의 원칙을 지키면서 하위 컴포넌트로 전달되어 호출되면 상위 컴포넌트의 상태에 영향을 미치는데, 이것을 state 끌어올리기라고 한다.

이 프로젝트에서도 state 끌어올리기를 사용했는데,
각각의 댓글 컴포넌트에서 삭제 버튼을 누르면 상위의 피드 데이터를 변경해야 했다.
이를 위해 deleteComment()는 comment를 인자로 받고,전달받은 comment를 Feed컴포넌트에 있는 comments state에 setComments를 사용해 업데이트 한다.

Reference

profile
Why?에서 시작해 How를 찾는 과정을 좋아합니다. 그 고민과 성장의 과정을 꾸준히 기록하고자 합니다.

0개의 댓글