TIL - mock data를 활용하여 article component 각각에 댓글 추가 기능 구현하기

김현재·2021년 8월 24일
0
post-thumbnail

인스타그램 피드 하나에 대한 댓글들을 mock data로 생성하여 받아오도록 하였다.
그러나, 문제가 생겼는데..그 문제는 댓글이 생성되는 함수가 망가진 것..!
다시 이 mock data를 통해서 원하는 지점에서 입력한 댓글이 나타나도록 했는지 정리해보았다.

1. 중첩된 data 분석하기

가장 어려웠던 첫번 째 이유는, 중첩된 data 구조가 전혀 감이 오지 않았기 때문이다.

기존에는 1중 object만 사용했기에 눈에 바로 들어오고, 그렇기 때문에 state로 받고, props로 보내는데 map, filter 같은 기능을 많이 사용할 필요가 없었다.

허나, 이번과 같이 2중 object로 늘어나면...여러겹으로 풀어줘야 하기 때문에 map 파티가 일어난다..

// feeds : 모든 feed에 대한 데이터
[
	// feed 1
  {
    "id": 1,
    "profile": "/images/cheoljinJu/food.jpeg",
    "userName": "CheoljinJu",
    "url": "/images/cheoljinJu/food.jpeg",
		// feed1에 대한 댓글들
    "comments": [
      {
        "id": 1,
        "userName": "현재님",
        "comment": "안녕하세요!",
        "isUser": false
      },
      {
        "id": 2,
        "userName": "동희님",
        "comment": "오히려 좋아",
        "isUser": false
      }
    ]
  },
	// feed 2
  {
    "id": 2,
    "profile": "/images/cheoljinJu/food.jpeg",
    "userName": "CheoljinJu",
    "url": "/images/cheoljinJu/food.jpeg",
		// feed 2에 대한 댓글들
    "comments": [
      {
        "id": 1,
        "userName": "승찬님",
        "comment": "반갑습니다!",
        "isUser": false
      },
      {
        "id": 2,
        "userName": "성환님",
        "comment": "감사합니다.",
        "isUser": false
      }
    ]
  }
]

우선 위의 data예시를 분석해보겠다.

가장 겉면에는 모든 feed의 정보를 가져오도록 하였다.

즉, [{feed1}, {feed2}] 의 형태이다.

그리고 각 feed 안에는 {coments: {}, {}} 이런 형태로 댓글들이 들어있다.

정리하면, 가장 바깥에서 각 feed의 대한 댓글들을 보려면 feeds.map(item => item.comments) 와 같이 작성해야된다. (map 1번)

그리고, comments 들 중에서 딱 1줄의 comment 만 끌어오고 싶은 경우,

const comments = feeds.map(item => item.comments);
const comment = comments.map(item => item);
return comment;

위와 같이 map을 두번 돌려줘야 한다..

comment 하나까지는 2겹의 object를 뚫고 들어가야된다는 것이다.



2. 어떤 데이터를 끌고 올 것인지 고민하기

그 다음으로 고민할 것은 각 데이터를 어느 component까지 끌고 올 것이냐 이다.

지금 나의 컴포넌트 구조는 main > contents > content > replies > reply 형태로 연결되어있다.

데이터를 받아 화면에 나타내는 과정만 우선 보면,

  1. 우선, 각 content 별로 feed 를 받아와야 한다. (main에서 map 발동!)
  2. 그리고 contentreplies 부분에 comments 를 받아와야 된다.
  3. 그리고 repliesreply 하나 하나 마다 comment 를 받아와야 한다. (replies에서 map 발동!)

그러면 역발상으로, 입력해준 데이터는 어떻게 움직여야 할까?

데이터를 입력해주는 형태는 commentForm > content > contents > main 형태로 연결되어 있다.

  1. 우선, commentForm 에 입력한 내용을, comment 조건에 부합하도록 오브젝트로 정리한다.
  2. 그 정리한 내역을 content 에 해당하는 object 내 comments 안에 추가로 넣어주면 된다.
  3. 그리고, 그 추가된 내용을 복제하여 다시 main state로 보내어 업데이트 해주면, 변경된 댓글 내역이 화면에 나타나게 된다.
  4. commentForm이랑 repliescontent 에서 만나니까, content 에 해당하는 object 레벨에서 결합해주면 된다. 즉, feed 부분에다가 추가해주면 된다.
[
	// feed 1
  {
    "id": 1,
    "profile": "/images/cheoljinJu/food.jpeg",
    "userName": "CheoljinJu",
    "url": "/images/cheoljinJu/food.jpeg",
		// feed1에 대한 댓글들
    "comments": [
      {
        "id": 1,
        "userName": "현재님",
        "comment": "안녕하세요!",
        "isUser": false
      },
      {
        "id": 2,
        "userName": "동희님",
        "comment": "오히려 좋아",
        "isUser": false
      },
      // 여기에다가 새로운 댓글에 대한 object를 생성할거에요
      {}
    ]
  },


3. 추가하기 구현해보기

구현할 때 댓글을 단 위치를 확인하기 위하여 id 를 사용할 것이다. 각 feed 의 맨 첫 줄에는 id 라는 key값이 있는데, 이는 몇번째 feed인지를 나타내주는 키이다.

그렇기 때문에, 이 database를 우선...댓글을 입력해주는 commentForm 까지 잘 끌어내려줘야한다.

그 후, 지금 입력값이 속해있는 feed object와 입력값을 부모에게 전달해준다

onSubmit = (event, content) => {
// 여기서 content는 부모로부터 받아온 하나의 feed object로 
// 이곳에 기재되어 있는 id를 통해 몇번째 feed에 작성되었는지를 알 수 있습니다.
    event.preventDefault();
    const comment = this.inputRef.current.value;
		// 작성된 내용과, 내용이 기재되어야 될 feed를 함께 부모에게 전달합니다.
    comment && this.props.onSubmit(comment, content);
    this.formRef.current.reset();
  };

그러고 나서

  1. 부모 영역에서, 입력값을 해당 feed object에 추가시켜주고,
  2. 그 추가된 feed object를 전체 데이터베이스에 반영한다.
  3. 그리고 그 반영된 데이터 베이스를 setState 를 사용하여 state 에 업데이트 사항이 반영되도록 한다.

💡 주의 ) data를 직접적으로 변환하다보면 충돌이 발생할 수 있으니 spread operator를 사용하여 데이터를 copy한 후 덮어쓰기 하도록 한다.

handleAdd = (comment, content) => {
		// 1 -1. 받아온 comment를 comments object에 추가
    const commentList = [
      ...content.comments,
      { id: Date.now(), userName: "hyun__jjae", comment },
    ];
		// 1 -2. 추가된 comments를 feed object에 추가
    const newFeed = { ...content, comments: commentList };
		// 2. 추가된 feed object를 전체 database에 반영되도록 한다
    const feeds = this.state.feeds.map(item => {
      if (item.id === content.id) {
			// 2 -1. 신규 입력된 댓글 component가 가지고 있던 id랑 일치하는 feed object가
			//       신규 댓글이 입력된 object로 덮어씌워지도록 한다.
        return newFeed;
      }
      return item;
    });
	  // 3. 새로 반영된 데이터베이스를 state에 업데이트 한다
    this.setState({ feeds });
  };


고려할 사항

추가되고 빠져야 될 요소들이 data의 어느 부분에 위치하는지, 어떻게 덮어씌워져야 하는지 로직을 먼저 세워보고, 그 다음에 코드로 구현하자.

컴퓨터로 생각하기 어려우면 손코딩으로 하나하나씩 움직여볼 것!



PS

이 어려운 것을 포기하지 않고 구현해주신 철진님께 무한한 감사를 보냅니다.

profile
쉽게만 살아가면 재미없어 빙고!

0개의 댓글