리액트를 다루는 기술
올립
chapter6. 컴포넌트 반복

6장. 컴포넌트 반복

Deep Dive - React 배열 index를 key로 사용하면 안되는 이유

map() 함수를 사용할 때 key 값으로 index를 자주 사용한다.
그러나, 공식문서에서는 key 값으로 index 사용을 권장하지 않는다.

왜 key를 사용해야하는가?

리액트에서 key는 어떤 원소에 변동이 있었는지 알기 위해 사용한다.
Virtual DOM을 비교하는 과정에서 key를 이용하여 정확하고 빠르게 변화를 추론하고 DOM 트리를 올바르게 업데이트하는 데 도움을 준다.

그런데 왜 index를 사용하면 안되는가?

미묘하고 복잡한 버그가 생길 수 있다.

import React, { useEffect, useState } from "react";
 
const Example = () => {
  const [list, setList] = useState([
    { name: "철수" },
    { name: "영희" },
    { name: "민수" },
  ]);
 
  const addItem = () => {
    setList([{ name: "정국" }, ...list]);
  };
 
  const delItem = () => {
    setList(list.filter((l) => l.name != "철수"));
  };
 
  return (
    <>
      {/* 추가 버튼과 삭제 버튼*/}
      <input type="button" value="추가" onClick={addItem} />
      <input type="button" value="삭제" onClick={delItem} />
 
      <h2> Show Problem Example</h2>
      {list.map((v, index) => (
        <div key={index}>
          {v.name}, idx: {index} <input type="text" />
        </div>
      ))}
    </>
  );
};
 
export default Example;

key의 규칙

  1. key는 형제 간에 고유한다. 그러나 다른 배열의 JSX 노드에 동일한 키를 사용하는 것은 OK
  2. key는 변경되어서는 안 된다.
  3. 렌더링하는 동안 key를 생성하면 안 된다.

어떤 데이터가 key로 적합한가?

List 데이터에서 유니크한 값을 key로 사용해야한다.

  • 데이터베이스의 데이터: 데이터가 데이터베이스에서 오는 경우 본질적으로 고유한 데이터베이스 키/ID를 사용

  • 로컬에서 생성된 데이터: 데이터가 로컬에서 생성되고 유지되는 경우 항목을 생성할 때 처럼 증분 카운터나 메소드를 사용

    • crypto.randomUUID()
    • shorid
    var shortid = require("shortid");
    function createNewTodo(text) {
      return {
        id: shortid.generate(),
        text,
      };
    }

배열 index를 key로 사용할 수 있는 경우?

  1. 배열과 각 요소가 static이며 computed 되지 않고 변하지 않아야 한다.
  2. 데이터 내부에 id로 쓸만한 unique 값이 없을 경우
  3. 데이터가 결코 reordered or filtered 되지 않을 경우

요약

Q. A. react에서 key는 Virtual DOM을 비교하는 과정에서 정확하고 빠르게 변화를 추론하고 올바르게 업데이트하기 위해서 사용해야합니다. key를 사용할 때 주의해야할 점은 고유한 값을 사용해야한다는 것이고, 그렇기 때문에 배열의 index를 key로 사용하는 것은 지양해야합니다. 배열의 요소가 추가되거나 삭제되면 index의 값도 변동이 생겨 버그가 발생할수도 있기때문입니다.

출처