[react] unique "key" prop에러

·2022년 5월 3일
1

개발 기록

목록 보기
25/68

문제

map메서드를 사용하는 부분에서 다음과 같은 에러가 발생했다.

처음에는 오류 문구 그대로 key prop을 주지 않아서 발생한 거라 생각해서 빠진 부분을 수정했는데 오류는 해결되지 않았다!🙀 심지어 수정하고나서 map을 사용한 다른 부분들도 이런 오류가 추가로 발생했다.

해결

map 함수의 규칙 : 사용될 요소의 최상위 요소에 key 값을 부여해야함.

원인은 다음의 규칙을 어겨서 오류가 난 것이었다. 내가 작성한 코드로 설명을 하자면

{e.lnb.map((el) => (
		<>
        	<li className="lnb-item" key={el}>
            	<a href="#">{el}</a>
        	</li>
		</>
   ))}

jsx는 최상위에 무조건 감싸는 엘리먼트가 존재해야한다. 하지만 감싸는 엘리먼트가 스타일도 없고 역할도 없다면 저렇게 빈 태그를 사용해 작성할 수 있다.
그래서 map메서드 내에서도 저렇게 코드를 작성했다. 그리고 저 빈 태그는 의미가 없기에 li 태그에 key값을 줘야한다 생각했다.

하지만 위 코드는 li 태그가 내부의 a 태그를 감싸는 최상위 감싸는 엘리먼트이기 때문에 최상위 빈 태그가 없어도 문법적으로 오류가 나지 않는다.

{e.lnb.map((el) => (
      <li className="lnb-item" key={el}>
          <a href="#">{el}</a>
      </li>
   ))}

이렇게 최상위 엘리먼트를 가져야한다는 규칙map 함수의 규칙도 모두 지키게 되었다.

그럼 다음의 경우를 보자

{data.map((category, index) => (
        <>
          <Category
            dish={category.data}
            category={category.key}
            display={index === 0 ? "block" : isFold ? "none" : "block"}
          />
          <Horizon
            display={
              index === data.length - 1 ? "none" : isFold ? "none" : "block"
            }
          />
        </>
      ))}

이 경우는 어떻게 해결해야 할까? 최상위 빈 태그를 삭제한다면 jsx의 감싸는 최상위 엘리먼트를 가져야한다는 규칙에 어긋나게 된다. 그런데 빈 태그에는 key prop을 줄 수 없다.

그래서 두 규칙을 모두 만족하기 위해 Wrapper 컴포넌트를 만들었다. 그리고 그 Wrapper에다 key prop을 줬다.

const CategoryWrapper = styled.div``;
{data.map((category, index) => (
        <CategoryWrapper key={category.key}>
          <Category
            dish={category.data}
            category={category.key}
            display={index === 0 ? "block" : isFold ? "none" : "block"}
          />
          <Horizon
            display={
              index === data.length - 1 ? "none" : isFold ? "none" : "block"
            }
          />
        </CategoryWrapper>
      ))}

이렇게 하면 두 규칙을 모두 만족하며 오류를 해결할 수 있다.

Fragment

두번째 케이스의 해결법을 다시 생각해보자.

const CategoryWrapper = styled.div``;

.........................👀❓
저렇게 의미없는 빈 컴포넌트를 만든다고?? 너무 비효율적인데...페이스북에서 저렇게 만들었을까....???

그래서 찾아봤더니 역시나 방법이 있었다. 리액트에서 제공하는 Fragment 컴포넌트를 사용하면 된다.

사실 계속 빈 태그라고 불렀던 것도 Fragment이다. 차이점은 빈 태그 형태로 된 Fragment는 key prop을 줄 수 없지만 <Fragment>에는 key prop을 줄 수 있다.

그럼 저 이상한 코드를 고쳐보자

import { Fragment } from "react";
{data.map((category, index) => (
        <Fragment key={category.key}>
          <Category
            dish={category.data}
            category={category.key}
            display={index === 0 ? "block" : isFold ? "none" : "block"}
          />
          <Horizon
            display={
              index === data.length - 1 ? "none" : isFold ? "none" : "block"
            }
          />
        </Fragment>
      ))}

👏👏👏👏👏👏👏👏👏👏👏 해 👏👏👏👏👏👏👏👏👏👏👏 결 👏👏👏👏👏👏👏👏👏👏👏

참고자료

0개의 댓글