React에서 배열을 엘리먼트 리스트로 만드는 방식은
자바스크립트에서와 거의 동일하다
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li>{number}</li>
);
return (
<ul>{listItems}</ul>
)
엘리먼트 모음을 만들고 중괄호를 이용하여 JSX에 포함시킬 수 있다
위 코드는 각 항목에 key 를 넣어야 한다는 경고가 표시된다
key 는 엘리먼트 리스트를 만들 때 포함해야 하는 특수한 문자열 속성이다
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>{number}</li>
);
return (
<ul>{listItems}</ul>
)
위와 같이 키를 넣어주어야 한다
key는 React 가 어떤 항목을 변경, 추가, 삭제할지 식별하는 데 사용된다
각 엘리먼트를 식별하고 안정적인 고유성을 부여하기 위해 지정해줘야 한다
key를 줄 때는 리스트의 다른 항목들 사이에서 고유한 값을 가지는 문자열을 사용하는 것
대부분은 데이터의 id를 키로 사용한다
렌더링 한 항목에 대해 안정적인 id가 없다면 최후의 수단으로
리스트의 index를 key로 사용할 수 있다는데 이러한 방식은 좋지 않다
항목의 순서가 바뀌는 경우 key에 인덱스를 사용한다면
성능 저하 이슈나 컴포넌트의 상태 관련한 문제를 발생시킬 수 있다
key is an anti-pattern
키를 생략 시 React는 기본적으로 index를 사용한다 - index로 key를 지정하는 것은 의미가 없다
DOM 노드의 자식들을 재귀적으로 처리할 때,
React는 두 리스트를 순회하고 차이점이 있으면 변경을 생성한다
// 기존 배열
<ul>
<li>first</li>
<li>second</li>
</ul>
// third 항목 추가
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
기존 배열의 끝에 third를 추가하여 아래와 같이 리스트 엘리먼트를 변경하였을 경우
두 트리의 변경은 예상대로 잘 작동한다
// 기존 배열
<ul>
<li>Duke</li>
<li>Villanova</li>
</ul>
// Connecticut 추가
<ul>
<li>Connecticut</li>
<li>Duke</li>
<li>Villanova</li>
</ul>
하지만 위와 같이 기존 배열의 순서를 변경하는 경우
React는 두 배열을 재귀적으로 순회하면서 비교하기 때문에
성능에 좋지 않다 - 형편 없는 트리 변환을 할 것이다
모든 li 자식 엘리먼트를 변환해야 하는 비효율을 가져온다
이러한 문제를 해결하기 위해 React는 키 속성을 지원한다
기존 배열과 변환된 배열의 차이를 key를 통해 구분한다
// 기존 배열
<ul>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
// Connecticut이 추가된 배열
<ul>
<li key="2014">Connecticut</li>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
key를 통해 React는 2014 를 키로 가지는 엘리먼트가 추가되었고
2015, 2016은 이동만 하면 되는 것을 알 수 있다
엘리먼트에 일반적으로 가지고 있는 식별자를 통해 key를 지정하면 된다
key는 형제 사이에서만 유일하면 되고, 전역에서 유일한 필요는 없다
index를 키로 사용하면 항목들이 재배열되는 경우 비효율적으로 동작한다
또한 state와 관련된 문제를 야기할 수 있기 때문에 사용하지 않는다
컴포넌트 인스턴스는 key를 기반으로 갱신되고 재사용되기 때문
재조정 알고리즘은 구현상의 세부사항이다
React는 항상 전체 앱을 재렌더링할 수도 있지만 최종 결과는 항상 같다
재렌더링은 컴포넌트의 render를 호출하는 것이지
React가 컴포넌트를 언마운트 시키고 다시 마운트 하는 것이 아니다
규칙에 따라 렌더링 전후에 변경된 부분만을 적용하는 것이다
한 종속 트리가 그 형제 사이에서 이동했다는 사실을 표현할 수는 있지만
완전 다른 곳으로 이동했다는 사실을 표현할 수는 없다
이런 경우 전체 종속트리를 재렌더링하게 된다
map 함수 내부의 엘리먼트에 key를 넣어주면 된다
key와 비슷한 이름이 필요하더라도 key와는 다른 이름의 props name을 사용해야 한다