먼저 JavaScript에서 리스트를 어떻게 변환하는지 살펴봅시다.
아래는 map()
함수를 이용하여 numbers
배열의 값을 두배로 만든 후 map()
에서 반환하는 새 배열을 doubled
변수에 할당하고 로그를 확인하는 코드입니다.
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);console.log(doubled);
이 코드는 콘솔에 [2, 4, 6, 8, 10]
을 출력합니다.
React에서 배열을 엘리먼트 리스트로 만드는 방식은 이와 거의 동일 합니다.
엘리먼트 모음을 만들고 중괄호 {}
를 이용하여 JSX에 포함 시킬 수 있습니다.
아래의 JavaScript map()
함수를 사용하여 numbers
배열을 반복 실행합니다. 각 항목에 대해 <li>
엘리먼트를 반환하고 엘리먼트 배열의 결과를 listItems
에 저장합니다.
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) => <li>{number}</li>);
listItems
배열을 <ul>
엘리먼트 안에 포함하고 DOM에 렌더링합니다.
ReactDOM.render(
<ul>{listItems}</ul>, document.getElementById('root')
);
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => <li>{number}</li> ); return (
<ul>{listItems}</ul> );
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />, document.getElementById('root')
);
이 코드를 실행하면 리스트의 각 항목에 key를 넣어야 한다는 경고가 표시됩니다. “key”는 엘리먼트 리스트를 만들 때 포함해야 하는 특수한 문자열 어트리뷰트입니다. 다음 섹션에서 key의 중요성에 대해서 더 설명하겠습니다. 이제 numbers.map()
안에서 리스트의 각 항목에 key
를 할당하여 키 누락 문제를 해결하겠습니다.
Key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕습니다. key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야 합니다.
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}> {number}
</li>
);
Key를 선택하는 가장 좋은 방법은 리스트의 다른 항목들 사이에서 해당 항목을 고유하게 식별할 수 있는 문자열을 사용하는 것입니다. 대부분의 경우 데이터의 ID를 key로 사용합니다.
const todoItems = todos.map((todo) =>
<li key={todo.id}> {todo.text}
</li>
);
렌더링 한 항목에 대한 안정적인 ID가 없다면 최후의 수단으로 항목의 인덱스를 key로 사용할 수 있습니다.
const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs <li key={index}> {todo.text}
</li>
);
항목의 순서가 바뀔 수 있는 경우 key에 인덱스를 사용하는 것은 권장하지 않습니다. 이로 인해 성능이 저하되거나 컴포넌트의 state와 관련된 문제가 발생할 수 있습니다. Robin Pokorny’s가 작성한 글인 인덱스를 key로 사용할 경우 부정적인 영향에 대한 상세 설명을 참고하시길 바랍니다. 리스트 항목에 명시적으로 key를 지정하지 않으면 React는 기본적으로 인덱스를 key로 사용합니다.
So many times I have seen developers use the index of an item as its key when they render a list.
todos.map((todo, index) => (
<Todo {...todo} key={index} />
));
}
It looks elegant and it does get rid of the warning (which was the ‘real’ issue, right?). What is the danger here?
It may break your application and display wrong data!
Let me explain, a key is the only thing React uses to identify DOM elements. What happens if you push an item to the list or remove something in the middle? If the key is same as before React assumes that the DOM element represents the same component as before. But that is no longer true.
예시: 올바른 Key 사용법
function ListItem(props) {
// 맞습니다! 여기에는 key를 지정할 필요가 없습니다. return <li>{props.value}</li>;}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// 맞습니다! 배열 안에 key를 지정해야 합니다. <ListItem key={number.toString()} value={number} /> );
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
경험상 map()
함수 내부에 있는 엘리먼트에 key를 넣어 주는 게 좋습니다.
React에서 key는 힌트를 제공하지만 컴포넌트로 전달하지는 않습니다. 컴포넌트에서 key와 동일한 값이 필요하면 다른 이름의 prop으로 명시적으로 전달합니다.
const content = posts.map((post) =>
<Post
key={post.id} id={post.id} title={post.title} />
);
위 예시에서 Post
컴포넌트는 props.id
를 읽을 수 있지만 props.key
는 읽을 수 없습니다.