TIL 13 | React 리스트와 Key

sammy1101·2021년 4월 5일
0
post-thumbnail

오늘은 map 함수 적용시 key props를 부여하는 이유에 대해 알아보겠습니다.
제가 직접 작성한 코드와 함께 리스트와 key 부분에 대해 소개하는 리액트 공식문서를 보면서 이해되지 않았던 부분들에 대해 다뤄보려합니다.

에러

map함수를 이용하여 댓글을 보여주는 Comment 컴포넌트를 화면에 보여주는데
에러 메세지를 콘솔에서 확인할 수 있었다.

에러 메세지를 해석해보면 리스트 안의 자식요소에 고유한 key 값을 주지 않아서 에러가 났다는 것을 알 수 있다.

key props를 써야하는 이유는 리액트 공식문서에 잘 나와있다.(공식문서를 잘 확인 하는 습관을 가지자)

[https://ko.reactjs.org/docs/handling-events.html]

“key”는 엘리먼트 리스트를 만들 때 포함해야 하는 특수한 문자열 속성입니다. 리스트의 각 항목에 key를 할당하여 키 누락 문제를 해결하겠습니다.

수정전 코드

Main.js 의 return() 안의 해당 엘리먼트

<ul>
               {this.state.commentList.map((commentText) => {
                 return (
                   <Comments
                     id={this.state.commentId}
                     content={commentText.comment}
                   />
                 );
               })}
             </ul>

수정 전 Commnent 컴포넌트

import React, { Component } from "react";
import "../Comment/Comment.scss";

class Comments extends Component {
  render() {
    // console.log("props content:" + this.props.content);
    // console.log("props id:" + this.props.id);
    return (
      <li className="comment_list">
        <span className="comment_name">{this.props.id}</span>
        {this.props.content}
      </li>
    );
  }
}

export default Comments;

Main.js 의 return() 안의 해당 엘리먼트
수정 후

수정 후 Commnent 컴포넌트

공식문서: Key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕습니다. key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야 합니다.

항목의 순서가 바뀔 수 있는 경우 key에 인덱스를 사용하는 것은 권장하지 않습니다. 이로 인해 성능이 저하되거나 컴포넌트의 state와 관련된 문제가 발생할 수 있습니다.

자식에 대한 재귀적 처리
DOM 노드의 자식들을 재귀적으로 처리할 때, React는 기본적으로 동시에 두 리스트를 순회하고 차이점이 있으면 변경을 생성합니다.

예를 들어, 자식의 끝에 엘리먼트를 추가하면, 두 트리 사이의 변경은 잘 작동할 것입니다.

<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

React는 두 트리에서

  • first
  • 가 일치하는 것을 확인하고,
  • second
  • 가 일치하는 것을 확인합니다. 그리고 마지막으로
  • third
  • 를 트리에 추가합니다.

    하지만 위와 같이 단순하게 구현하면, 리스트의 맨 앞에 엘리먼트를 추가하는 경우 성능이 좋지 않습니다. 예를 들어, 아래의 두 트리 변환은 형편없이 작동합니다.

    자식들이 key를 가지고 있다면, React는 key를 통해 기존 트리와 이후 트리의 자식들이 일치하는지 확인합니다. 예를 들어, 위 비효율적인 예시에 key를 추가하여 트리의 변환 작업이 효율적으로 수행되도록 수정할 수 있습니다.

    index를 key로 쓰면 안되는 이유

    공식문서: 인덱스를 key로 사용 중 배열이 재배열되면 컴포넌트의 state와 관련된 문제가 발생할 수 있습니다. 컴포넌트 인스턴스는 key를 기반으로 갱신되고 재사용됩니다. 인덱스를 key로 사용하면, 항목의 순서가 바뀌었을 때 key 또한 바뀔 것입니다. 그 결과로, 컴포넌트의 state가 엉망이 되거나 의도하지 않은 방식으로 바뀔 수도 있습니다.

    공식문서에서 이해가 잘 안 되었던 부분

    Key는 배열 안에서 형제 사이에서 고유해야 하고 전체 범위에서 고유할 필요는 없습니다. 두 개의 다른 배열을 만들 때 동일한 key를 사용할 수 있습니다.

    컴포넌트에서 key와 동일한 값이 필요하면 다른 이름의 prop으로 명시적으로 전달합니다.

    function Blog(props) {
      const sidebar = (
        <ul>
          {props.posts.map((post) =>
            <li key={post.id}>
              {post.title}
            </li>
          )}
        </ul>
      );
      const content = props.posts.map((post) =>
        <div key={post.id}>
          <h3>{post.title}</h3>
          <p>{post.content}</p>
        </div>
      );
      return (
        <div>
          {sidebar}
          <hr />
          {content}
        </div>
      );
    }

    위 예제에서 Post 컴포넌트는 props.id를 읽을 수 있지만 props.key는 읽을 수 없습니다.=>구체적인 이유는 내일 다시 확인할 예정이다.

    컴포넌트에서 key와 동일한 값이 필요하면 다른 이름의 prop으로 명시적으로 전달합니다. 결론적으로는 컴포넌트 하나씩을 잘 관리하기 위해서 이다.

    profile
    안녕하세요! 프론트엔드 개발자 새미입니다:D

    관심 있을 만한 포스트

    0개의 댓글