물론 map 함수 를 이용해 여러개의 컴포넌트 렌더링 시 key 를 포함하지 않으면 경고창이 뜨기 때문에 경고창을 없애기 위해 key 를 포함시킨다.
하지만 왜??!! 꼭 넣으라고 하는 걸까?
이는 react 가 효율적으로 리렌더링하는데, 즉 성능에 큰 역할을 하기 때문이다.
만약 ['a', 'b', 'c', 'd'] 가 있고
'b' 를 삭제한다면
'a'-> 'a' , 'b' -> 'c' , 'c' -> 'd', 'd' -> 삭제 로 변경할 것이다.
각 key 로 이름을 붙여주지 않으면 react 는 어디가 삭제되고 어디가 변경됐는지 모르기 때문이다.
const feed1Comment = [
{
nickName: 'tjdgus05',
commentText: '이쁘다~~',
commentId: 1,
heartActive: true,
},
{
nickName: 'ria',
commentText: '하늘이 정말 이뻤네~',
commentId: 2,
heartActive: false,
},
{
nickName: 'peter',
commentText: '오늘 나갔었구나',
commentId: 3,
heartActive: false,
},
];
{comments.map((comment, i) => (
<Comment
onHeartClick={onHeartClick}
onDeleteComment={onDeleteComment}
comment={comment}
key={i}
/>
))}
이렇게 key 값을 주면 어떤 엘리먼트가 삭제되고 어떤 엘리먼트에서 수정이 되고 되지 않았는지 React가 정확히 인식할 수 있게 된다.
이를 통해, 수정이 되지 않은 부분은 그대로 두고 변경된 부분만 리렌더링한다. 우리가 생각했던 대로 필요한 부분만 리렌더링 됨을 알 수 있다.
React 가 DOM elements 인식하는 유일한 방법은 key 를 통해서이다.
하지만 key 를 지정해 주지 않으면 index 를 key 로 사용한다.
key 를 사용하지 않았을 때 모든 엘리먼트들을 변경한 것과는 확연히 다른 성능 차이를 보임을 알 수 있다.
또한, 더 큰 문제는 우리가 생각한 대로 react 가 움직이지 않을 수 있기 때문이다.
item을 새로 추가하거나 삭제하면 내가 생각한 그 item 이 삭제되지 않고 다른 아이템이 수정되어 없어진 것처럼 보이게 되게 될 수 있다. 또, 이 상태에서 sort를 하면 react 는 정말 혼돈의 카오스가 된다. 이를 map 해서 나에게 보이면 이제 내가 혼돈의 카오스가 될 수 있다.
(Robin Pokorny’s) Index as a key is an anti-pattern 자세한 내용은 여기서 확인해 볼 수 있고
Index as a key is an anti-pattern 예시 에서 직접 item을 추가해보며 어떤 문제가 생기는지 확인해 볼 수 있다. 한번해보면 다음부턴 무조건 key에 index가 아닌 고유한 값을 사용하게 될 것이다.
let itemId = 1;
const createItem = (text) => {
id: itemId++,
text
}
import { nanoid } from 'nanoid';
const createItem = (text) => {
id: nanoid(),
text
하지만 절대 변경사항이 없는 컴포넌트들을 map 하는 거라면 key를 index로 해도 되지 않을까 조심스럽게 생각해 본다.
Robin Pokorny는 실제로 아래 3가지를 모두 만족하는 상황이라면 index 를 키로 사용해도 안전할 것이라고 했다.
1. 리스트나 items 가 정적이고, 계산되거나 수정하지 않는 것일 때
2. 리스트에 있는 item 들이 id가 없을 때 (id 가 있다면 그냥 왠만하면 쓰라는 것 같다)
3. 리스트가 절대 재배치되거나 필터 될 일이 없을 때