기본

const numbers = [1,2,3,4,5];
const doubled = numbers.map((n) => n * 2);
console.log(doubled) // [2,4,6,8,10]

위와 같은 방식으로

const numbers = [1,2,3,4,5];
const listItems = numbers.map((number) =>
    <li>{numbers}</li>
);

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')
)

위 코드는 "Warning: Each child in a list should have a unique 'key' prop. 와 같은 오류를 발생시키는데 <li> 태그에 문자열 key 속성을 주면 해결된다. key는 엘리먼트 리스트를 만들 때 포함해야 하는 특수한 문자열 속성이다.

<li>{number}</li>

<li key={number.toString()}>
    {number}
</li>

key 속성

  • React가 항목을 변경, 추가, 삭제할 때 식별하는 것을 돕는다.
  • 항목의 순서가 바뀔 수 있는 경우 key에 인덱스를 사용하는 것을 권장하지 않음. 참고
  • 명시적으로 key를 지정하지 않으면 React는 기본적으로 인덱스를 key로 사용.
  • 자세한 설명
<li key={number.toString()}> ... </li>
<li key={todo.id}> ... </li>
<li key={index}> ... </li>

key 속성의 위치

  • 키는 주변 배열의 context에서만 의미가 있다. 예를 들어 ListItem 컴포넌트를 추출 한 경우 ListItem 안에 있는 <li> 엘리먼트가 아니라 배열의 <ListItem /> 엘리먼트가 key를 가져야 한다.
  • 경험상 map() 함수 내부에 있는 엘리먼트에 key를 넣어 주는게 좋다.
function ListItem(props) {
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <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')
);

Key의 값은 배열 안에서만 고유하면 됨

  • 배열 안에서 형제 사이에서만 고유하면 된다.
  • 전체 범위에서 고유할 필요는 없다.
function Blog(props) {
  const sidebar = (
    <ul>
      {props.posts.map((post) =>
        <li key={post.id}>
          {post.title}
        </li>
      )}
    </ul>
  );
  const content = props.posts.map((post) =>
    <div key={post.id}>
      <h3>{post.title}</h3>
      <p>{post.content}</p>
    </div>
  );
  return (
    <div>
      {sidebar}
      <hr />
      {content}
    </div>
  );
}

const posts = [
  {id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
  {id: 2, title: 'Installation', content: 'You can install React from npm.'}
];
ReactDOM.render(
  <Blog posts={posts} />,
  document.getElementById('root')
);

key는 컴포넌트로 전달되지 않음

const content = posts.map((post) =>
    <Post
        key={post.id}
        id={post.id}
        title={post.title} />
);
  • 위 예제에서 props.id는 읽을 수 있지만 props.key는 읽을 수 없음

중괄호 안으로 map 표현식 넣기

// Before
function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <ListItem key={number.toString()}
              value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}
  • 중괄호 안에 모든 표현식을 넣을 수 있으므로 map() 함수도 인라인 처리할 수 있다.
  • 가독성을 위해 적절히 사용하고 남발하지 않는게 좋다.
// After
function NumberList(props) {
  const numbers = props.numbers;
  return (
    <ul>
      {numbers.map((number) =>
        <ListItem key={number.toString()}
                  value={number} />
      )}
    </ul>
  );
}

참고자료