목표
8. 리스트와 Key
8-1. 여러 개의 엘리먼트 렌더링
- li 엘리먼트 모음을 만들고 중괄호 { } 를 활용해 JSX에 포함시킬 수 있다.
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li>{number}</li>
);
- 그 후, list 배열을 ul 엘리먼트에 포함하고 DOM에 렌더링한다.
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('root')
);
8-2. 기본 리스트 컴포넌트
function NumberList({ 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')
);
- numbers 배열을 받아서 순서 없는 엘리먼트 리스트를 출력하는데 문제가 없지만 콘솔을 확인해보면 리스트 각 항목에 key를 넣어야 한다는 경고가 표시된다.
- 참고로 경고가 표시되어도 리액트가 알아서 index를 쓰기 때문에 문제 없이 사용 가능하다.
8-3. Key
- Key는 리액트가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는 역할을 한다.
- 또한, 엘리먼트에 안정적인 고유성을 부여하는 역할을 수행한다.
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>{number}</li>
);
- Key를 선택하는 가장 좋은 방법은 리스트의 항목을 고유하게 식별할 수 있는 문자열을 사용하는 것이다.
- 대부분 데이터의 ID를 Key로 사용한다.
✏️ 참고
- 렌더링 한 항목에 대한 안정적인 ID가 없다면 최후의 수단으로 항목의 인덱스를 Key로 사용할 수 있다.
const listItems = numbers.map((number, index) =>
<li key={index.toString()}>{number}</li>
);
- 하지만, 항목의 순서가 바뀔 위험이 있으므로 인덱스를 key로 사용하는 것은 권장하지 않는다.
8-4. Key로 컴포넌트 추출하기
- Key는 리스트 즉, map() 함수 내부에 있는 엘리먼트에 넣어주는 것이 좋다. 예를 들어,
export default function List() {
const todos = [
{
id: 1,
do: "go to hospital"
},
{ id: 2, do: "go to cafe" },
{ id: 3, do: "eating dinner" }
];
const Item = (props) => {
return <li key={props.id}>{props.do}</li>;
};
const todoList = todos.map((todo) => <Item {...todo} />);
return <ul>{todoList}</ul>;
}
- map 함수 내부가 아닌 컴포넌트에 Key를 넣어주면 출력에는 문제가 없지만 콘솔을 확인해보면 아까 봤던 key를 넣어야 한다는 경고가 표시된다.
export default function List() {
const todos = [
{
id: 1,
do: "go to hospital"
},
{ id: 2, do: "go to cafe" },
{ id: 3, do: "eating dinner" }
];
const Item = (props) => {
return <li>{props.do}</li>;
};
const todoList = todos.map((todo) => <Item key={props.id} {...todo} />);
return <ul>{todoList}</ul>;
}
- 이번에는 map 함수 내부에 있는 컴포넌트에 Key를 넣어주면 콘솔에 에러가 뜨지 않고 잘 출력된다.
8-5. Key는 형제 사이에서만 고유한 값이어야 한다.
- 위의 코드에서 Key를 자식 컴포넌트로 넘겨주었다.
- 그렇다면 자식 컴포넌트는 Key 값을 알 수 있을까?
export default function List() {
const todos = [
{
id: 1,
do: "go to hospital"
},
{ id: 2, do: "go to cafe" },
{ id: 3, do: "eating dinner" }
];
const Item = (props) => {
return (
<li>
{props.key}
{props.do}
</li>
);
};
const todoList = todos.map((todo) => <Item key={todo.id} {...todo} />);
return <ul>{todoList}</ul>;
}
- props.key를 추가해서 위 코드를 실행해보면 다음과 같은 에러가 발생한다.
- 따라서, Key는 자식 컴포넌트로 전달되지 않으므로 key와 동일한 값이 필요하다면 다른 이름의 props로 넘겨주어야 한다.
const todoList = todos.map((todo) => <Item key={todo.id} id={todo.id} do={todo.do} />);
출처