react) map 함수 적용시 key props를 부여하는 이유

이명진·2021년 4월 5일
2

react - 이론

목록 보기
4/11

we code 리액트 미션 5를 수행하기 이전에 미션 4를 진행하면서 map에 대해 잘 모르고 있다고 생각하였고 미션 5를 진행하면서 map에의 활용 법에 대해서도 다시한번 생각해 보는 계기가 되었다.

4번 미션인 댓글들을 컴포넌트로 만들어서 재사용 하게 되었는데 ul안에 컴포넌트를 활용하여 map함수를 실행할 경우 리스트의 각 항목에 key를 넣어야 한다는 경고가 표시됩니다.

Each child in an array should have a unique “key” prop. 경고

key

key는 엘리먼트 리스트를 만들때 포함해야 하는 특수한 문자열 어트리뷰라고 합니다.
key는 react가 어떤 항목을 변경,추가 또는 삭제할지 식별하는 것을 돕습니다.
key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야 합니다.

<li key = {index}> 내용 </li>

이러한 형식으로 사용됩니다. 특히 map을 이용할 경우 필요한것 같습니다.
하지만 주의사항이 있습니다. 주의사항은 마지막에 다뤄보도록 하겠습니다.

컴포넌트 사용시 map함수에서 key 사용법

앞서 말한대로 key는 배열 내부의 엘리먼트에 지정해야 합니다.
자식 컴포넌트는 재사용 하기 이해서 사용되는데 이때 자식 컴포넌트에서 key를 사용하면 안됩니다.

잘못된 사용의 예 )

function 자식 컴포넌트 (props) {
  const value = props.value;
  return (
    <li key={value.toString()}>
      {value}
    </li>
  );
}

자식 컴포넌트 내부에서 사용하면 안됩니다.

부모의 값에서 자식 컴포넌트를 사용할때 사용해야 합니다

옳은 예 )

function 부모 컨포넌트(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <자식 컨포넌트 key = {number.toString()} value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

또한 key는 두개의 다른 배열을 만들때 동일한 key를 사용할수 있습니다.

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>
  );
}

주의 할점

리액트는 state에서 변경사항이 있는 부분만 캐치해서 리랜더링 해준다.
배열에 어떤 요소를 추가하면 리액트는 배열전체를 리랜더링 할까 하나만 리랜더링 할까 ?

배열의 key값을 고유하게 넘겨주었을 경우 리액트는 딱 한가지 요소만 리랜더링 한다.

리액트는 기존에 키값과 새로 추가된 키값을 비교하여 변화된 값을 새로추가하고랜더링 시켜준다.

예시로 세가지 값이 있다고 생각해 본다. 우리는 state를 사용하니 state를 사용하여 예시를 해보겠다. state값을 객체를 가지고 있는 배열이라고 생각해보자

[
{id:0 , content: 'hello'}
{id:1 , content: 'hello2'}
{id:2 , content: 'hello3'}

]

여기에서 {id:4 , content: 'hello4'}를 추가해보자
그러면 리액트는 이전값과 현재값을 비교한다. 그러면 key값이 id일때 내용은 같으니 추가하지 않고 id:4값을 추가한다. 이것만 랜더링 시켜준다.

map을 사용하였을때 index로 키값을 주면 안되는 이유

위의 상황을 고려했을경우 우리는 map함수를 사용할때 inde를 키값으로 주면 안된다는 것을 알수 있다.
key값을 index로 주게된다면 key값을 id로 주었을 경우와 다르게 맨앞에 값이 들어오게 되었을 경우

key: 0,  {id:4,  content:'ya!'},
key: 1,  {id:0,  content:'moya'},
key: 2,  {id:1,  content:'holly'},
key: 3,  {id:2,  content:'monya'},
key: 4,  {id:3, content:'hulkhulk'}

리액트가 판단했을때 매칭이 싹다 바뀐것으로 인지해버리게 된다.
결과적으로 비효율적으로 일처리가 진행되고 리액트의 장점을 사용하지 못하게 된다.

결과적으로 state로 배열을 관리한다면 map을 사용할때 key로 index를 사용하지말자. 배열의 처음이나 중간에 새로운 데이터가 들어올경우 그부분만을 캐치하지 못하게 된다.
사용하고 싶으면 데이터가 절때 바뀌지 않을때 권장된다.

profile
프론트엔드 개발자 초보에서 고수까지!

0개의 댓글