2022.06.21.
⚠ NOT unique key
React

react / issue / list / unique key

last modified: 2022-12-02

What is NOT unique key prop in React

not unique key error message

👉 introduction

처음 이 에러를 마주했을 때, List라는 단어에 넘어가 아래와 같은 코드에는 key를 주지 않았습니다. 사실 왜 이런 에러가 나오는지 관심이 없었습니다.

const colorChips = colors.map((color) => (
  <div>
    <p>color.name</p>
  </div>
));

이 에러는 동작을 멈추게 하지는 않지만 점점 콘솔 창을 지저분하게 만들었기 때문에 드디어 이 에러를 없애기로 합니다. 여기저기 key 값을 추가해 보기도 하고 구글에도 검색해 보면서 key 값을 추가할 때 무엇을 생각해야 하는지 적어놓기로 했습니다.

👉 key가 필요한 경우

React 공식 문서에서는 key를 다음과 같이 설명하고 있습니다.

(ENG) A “key” is a special string attribute you need to include when creating lists of elements.
(KOR) “key”는 엘리먼트 리스트를 만들 때 포함해야 하는 특수한 문자열 어트리뷰트입니다.

따라서 에러가 말하고 있는 “key” prop은 배열을 JSX에서 렌더 할 때 리스트 형태로 만들어지는 엘리먼트가 가져야 할 고유한 값을 말합니다. return 값이 배열인 메서드를 사용하여 엘리먼트를 만들었을 때, return된 배열의 각 아이템 최상위에 각각을 구별할 수 있도록 key prop이 추가되어야 하는 것을 의미합니다.

이 에러가 발생하지 않는 unique key의 조건은 렌더 시 반복되는 siblings 사이에서 유일할 것이므로, 아래와 같이 작성해도 에러는 발생하지 않습니다.

const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

return (
  <List>
  	<ul>
  	  {todoItems}
  	  <li>empty</li>
  	</ul>
  </List>
)

👉 not unique key

아래는 실제로 작성했던 코드를 바탕으로 한 에러 코드와 안티 패턴들입니다.

1. no key prop

// ❌ Error
const colorChips = colors.map((color) => (
  <div>
    <p>color.name</p>
  </div>
));

// 🔺
const colorChips = colors.map((color, index) => (
  <div key={index}>
    <p>color.name</p>
  </div>
));

2. same key in the siblings

// ❌ Error
return (
  <List>
  	<ul>
  	  {todoItems}
  	  {todoItems}
  	</ul>
  </List>
)

// 🔺
return (
  <List>
  	<ul>
  	  {todoItems}
    </ul>
    <ul>
  	  {todoItems}
    </ul>
  </List>
)

3. use index

// 🔺
const navItems = items.map((item, index) =>
  <li key={index}>
    <a href={item.to}>{item.title}</a>
  </li>
);

// ✅
const navItems = items.map((item) =>
  <li key={item.id}>
    <a href={item.to}>{item.title}</a>
  </li>
);

4. use rendering time

// 🔺
const todoItems = todos.map((todo) =>
  <li key={new Date().getTime()}>
    {todo.text}
  </li>
);

// ✅
const createNewTodo = (text) => ({
  completed: false,
  id: gernerateRandomId(),
  text
});
...
const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

참고:

Thank You for Visiting My Blog, Have a Good Day 😸
© 2022 Developer 나연, Powered By Gatsby.