리액트로 지출 관리를 해주는 가계부 프로젝트를 진행중에 F12를 눌러 콘솔을 봤더니 Each child in a list should have a unique "key" prop.라는 Warning이 발생했다.
해당 Warning은 아래의 ExpenseList라는 컴포넌트에서 발생한 경고 메세지이다. ExpenseList 컴포넌트는 내가 산 물건의 정보를 입력하면 map에 담긴 내가 산 물건의 정보 + 입력한 정보를 ExpenseItem으로 보내서 출력하는 역할을 가지고있다. 아래의 코드를 보고 다시 살펴보자
const ExpensesList = (props) => {
if(props.items.length === 0) {
return <h2 className="expenses-list__fallback">Found no expenses.</h2>;
}
return (
<ul className="expenses-list">
{props.items.map((expenses) => (
<ExpenseItem
title={expenses.title}
amount={expenses.amount}
date={expenses.date}
/>
))}
</ul>
);
};
위의 코드와 같이 지출을 추가하고 F12를 눌러 소스코드를 확인해보면 값을 넣을 때 바뀌는 부분이 모든 ExpenseItem컴포넌트가(<div>) 다 깜빡인다. 즉 expenseItem 컴포넌트가 전부 리렌더링된다는 뜻이다. (캡쳐해서 올리고싶은데 군대 사지방컴 이슈,,,)
그 이유는 map에서 보낸 원소에 대응되는 고유한 key값을 안 넣어주게 되면 컴포넌트의 트리에 달린 기존 자식 컴포넌트와 새로 추가된 자식 컴포넌트가 일치하는지 모르기 때문에 자식 컴포넌트 전체를 리렌더링 하는 것이다.
그래서 아래와 같이 map의 원소를 보내주면서 원소의 고유한 값인 expenses.id를 key로 지정해줘서 보내주게 되면 추가되는 <div> 즉 ExpenseItem 하나만 렌더링하게 된다. 더 이상 console에 Warning도 뜨지 않는다.
const ExpensesList = (props) => {
if(props.items.length === 0) {
return <h2 className="expenses-list__fallback">Found no expenses.</h2>;
}
return (
<ul className="expenses-list">
{props.items.map((expenses) => (
<ExpenseItem
key={expenses.id}
title={expenses.title}
amount={expenses.amount}
date={expenses.date}
/>
))}
</ul>
);
};
정리
1. key를 통해 기존 컴포넌트 트리와 원소를 추가한 이후 트리의 자식들이 일치하는지 확인하여 효율적으로 렌더링 하기 위해서 key를 사용한다. 변하는 부분만 렌더링해줄 수 있음.
2. key를 사용할 때는 변하지 않고, 예상 가능하며, 반드시 Unique한 값이 들어가야한다. key값은 단지 map배열 안에서만 고유하면 된다. 굳이 전역적으로 고유할 필요는 없다.
3. 배열의 인덱스를 key로 사용할 수 있지만 추천하는 방법은 아니다. 이유는 배열안의 원소들이 재배열되지 않는다면 상관이 없지만 만에 하나 재배열되는 경우 Unique한 값이라는 조건이 깨져버리기 때문이다.
'Frontend > React.js' 카테고리의 다른 글
[ReactJS로 영화 웹 서비스 만들기] #3.3 ~ 3.4 Recap ~ State Functions (0) | 2023.07.05 |
---|---|
[ReactJS로 영화 웹 서비스 만들기] #3.2 setState part Two (0) | 2023.06.19 |