Front-End/React

[React] map 함수 적용시 key props를 부여하는 이유

Voyage_dev 2022. 4. 17. 20:26

Key

React에선 기존에 한땀한땀 작성해야했던 배열을 map()이라는 함수를 이용해 element list로 반복 실행할 수 있다

key는 react가 어떤 항목을 변경, 추가 , 삭제할지 식별하며 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트로 지정해야 한다.

왜 필요할까?

위에서 언급했던 map이라는 함수로 요소를 하나하나 뿌려준다고 가정하자

리액트는 내용이 바뀔 때 즉, state값이 바뀔 때 마다 다시 랜더링을 하는데 10개의 리스트 중에 하나의 리스트만 바뀌었다면 리액트가 하나씩 리스트를 읽다가 어디서 달라졌는지 파악하고 전체를 재렌더링 한다. 그걸 방지하기 위해 각각의 요소들이 고유한 정체성을 가지도록 key값을 부여하는 것이다

그러면 리액트는 key값으로 변한 내용인지, 아닌지를 구별하고 전체 재 렌더링이 아닌 필요한 것만 변경해준다

Key엔 어떤 값을 써야할까?

key 값은 list에서 해당 항목을 고유하게 식별할 수 있는 문자열이 가장 좋다. 대부분의 경우 데이터의 ID를 key값으로 사용한다

key값을 부여 안 하면 어떻게 될까?

  • 너 동일한 형제들로 구성되어있는 list인데 유니크한 키 prop을 줘야 찾을 수 있어

나의 코드 예시

  • 인스타그램 클론 프로젝트를 진행하면서 반복적으로 노출되고 추가되는 영역인 댓글 부분을 map 함수를 이용해서 로직을 구현해 보았다
  • 하나의 ul태그 안에 여러 li 태그들로 추가되면서 보여주는 로직이다
  • commentList.map으로 돌리면서 해당 배열의 키값으로 인덱스를 부여했다
  • 각 인덱스에 들어간 요소들의 값을 가져올 수 있게 로직을 만들었다

주의

리액트는 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값을 추가한다. 이것만 랜더링 시켜준다.

나의 코드 문제점

Key에 index를 주면 안 된다!!

React 공식문서

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

 

key값을 index로 주게된다면 key값을 id로 주었을 경우와 다르게 맨 앞에 값이 들어오게 되었을 경우

key: 0,  {id:4,  content:'ya!'},
key: 1,  {id:0,  content:'wecode'},
key: 2,  {id:1,  content:'one'},
key: 3,  {id:2,  content:'two'},
key: 4,  {id:3, content:'voyage'}

key값을 배열의 index로 지정할 경우, 배열의 순서가 바뀌면 component의 state와 관련된 문제가 발생할 수 있다. component는 key를 기반으로 갱신/재사용되는데 index를 key로 사용하면, 항목의 순서가 바뀌었을 때 key도 변경된다. 따라서 state까지 의도치않게 변경될 수 있다

배열의 처음이나 중간에 새로운 데이터가 들어올 경우 그 부분만을 캐치하지 못하게 된다. 따라서 리액트가 판단했을 때 매칭이 싹 바귄것으로 인지해 버리게 된다. 결과적으로 비효율적으로 일처리가 진행되고 리액트의 장점을 사용하지 못하게 된다.

 

 

출처 : 아래의 사이트들을 보면서 큰 공부 하였습니다

https://dev-bomdong.tistory.com/m/12

https://velog.io/@nsunny0908/TIL-31-React-map-함수-적용시-key-props를-부여하는-이유

https://velog.io/@ljo094822/react-map-함수-적용시-key-props를-부여하는-이유

https://habitual-history.tistory.com/entry/React-map-함수-적용시-key-props를-부여하는-이유

https://ko.reactjs.org/docs/reconciliation.html#recursing-on-children