Post

[React] map 함수 사용 시 'Each child in a list should have a unique key prop' 오류 해결 방법

서론

리액트에서 배열에 map 함수를 적용할 때, ‘Each child in a list should have a unique “key” prop’이라는 콘솔 오류가 뜨는 경우가 있습니다. 오류가 나도 렌더링에 문제는 없지만, 되도록이면 오류는 잡아주는 게 좋기 때문에, 제가 사용한 방법을 공유하려고 합니다.

리액트의 key 오류

 

원인

제가 파악한 선에서 오류가 나는 경우는 3가지가 있었습니다.

  1. key 값이 없는 경우
  2. key 값이 잘못 입력된 경우
  3. key 값이 잘못된 위치에 입력된 경우

 

1. key 값이 없는 경우

key 값이 없는 경우, map 함수 내부에서 return 되는 JSX 코드의 최상위 태그에 key를 prop 형식으로 입력해 주면 됩니다.

코드 예시

1
<div key={data.id}>최상위 태그</div>

전체 코드 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const page = () => {
    // 배열 예시
    const cities = [
        { id: 1, name: "서울" },
        { id: 2, name: "부산" }
    ];
    
    return (
        <div>
            {
                cities.map((city) => {
                    return ( <div key={city.id}>{city.name}</div> )
                })
            }
            {/*
                결과:
                <div>서울</div>
                <div>부산</div>
            */}
        </div>
    )
}

export default page;

 

2. key 값이 잘못 입력된 경우

key 값이 잘못된 경우는 보통 2가지가 있습니다. key 값이 중복되거나, 리액트에서 key를 유니크 하다고 판단하지 않았을 경우입니다.

리액트에서 key 값이 중복되는 걸 오류라고 판단하는 이유는, 리액트는 key를 특정 항목을 변경, 삭제, 추가할 때 이를 파악하기 위한 식별자로 사용하기 때문입니다. 그렇기 때문에 key는 변경되지 않고, 함수 내에서 유일하게 사용되는 값이어야 합니다. 이건 아마 리액트가 Virtual DOM을 사용해 수시로 변경사항을 체크하기 때문이라고 생각이 되는데, Virtual DOM에 대한 자세한 내용은 여기에서 다뤘기 때문에, 시간 되시면 한번 확인해 주시면 감사하겠습니다. 🙂

key 값이 중복되는 경우, 어떤 key가 중복되는지 콘솔창에 나오기 때문에 중복되지 않게 데이터를 변경해 주시면 됩니다. key 값이 유니크하다고 판단하지 않는 경우는 아마 데이터에 ID라던가 그와 비슷한 object key가 없을 때 오류가 나는 것 같은데, 저같은 경우 객체에 ID를 추가해 key에 넣어줬더니 오류가 해결됐습니다.

오류가 났던 경우

1
2
3
4
5
6
7
8
9
10
const texts = [
    { text: "안녕하세요." },
    { text: "반갑습니다." }
];

texts.map((text) => {
    return (
        <div key={text.text}></div>
    )
});

오류가 나지 않았던 경우

1
2
3
4
5
6
7
8
9
10
const texts = [
    { id: 1, text: "안녕하세요." },
    { id: 2, text: "반갑습니다." }
];

texts.map((text) => {
    return (
        <div key={text.id}></div>
    )
});

 

3. Key 값이 잘못된 위치에 입력된 경우

key는 위에서 언급했던 것처럼 map 함수 내부에서 return 되는 JSX 코드의 최상위 태그에 넣어주면 되는데, 만약에 최상위에 빈 태그(React.Fragment)를 사용했다면, 리액트는 빈 태그를 최상위 태그로 인식하기 때문에 오류의 원인이 됩니다. 제가 확인한 해결 방법은 다음과 같습니다.

오류가 나는 경우 - 최상위 태그를 빈 태그로 감싼 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const cities = [
    { id: 1, name: "서울" },
    { id: 2, name: "부산" }
];

cities.map((city) => {
    return (
        <>
            <div key={city.id}>
                <div>{city.name}</div>
                <div>{city.name}</div>
            </div>
        </>
    )
});

오류가 나지 않는 경우 1 - 최상위 태그를 div로 변경

1
2
3
4
5
6
7
8
9
10
11
12
13
const cities = [
    { id: 1, name: "서울" },
    { id: 2, name: "부산" }
];

cities.map((city) => {
    return (
        <div key={city.id}>
            <div>{city.name}</div>
            <div>{city.name}</div>
        </div>
    )
});

오류가 나지 않는 경우 2 - 빈 태그를 React.Fragment로 변경

빈 태그(<></>)는 React.Fragment의 short syntax입니다. 빈 태그에 prop을 넣을 수는 없기 때문에 빈 태그를 React.Fragment로 변경해 key를 넣어주면 오류가 해결됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 컴포넌트 외부
import React from "react";

// 컴포넌트 내부
const cities = [
    { id: 1, name: "서울" },
    { id: 2, name: "부산" }
];

cities.map((city) => {
    return (
        <React.Fragment key={city.id}>
            <div>
                <div>{city.name}</div>
                <div>{city.name}</div>
            </div>
        </React.Fragment>
    )
});

 

레퍼런스

This post is licensed under CC BY 4.0 by the author.