Each child in a list should have a unique "key" prop.

2dean·2023년 6월 6일
0

react

목록 보기
2/2
import {TradeHistoryItem} from "@/components/UI/molecules";
import TransactionNoUpdateItem from "@components/UI/molecules/user/transaction/TransactionNoUpdateItem";
import {useEffect, useState} from "react";
import {useRecoilState, useRecoilValue} from "recoil";
import {UserAccountInfoState} from "@recoil/user/atoms";
import {useQuery} from "@tanstack/react-query";
import {TradeHistoryModel} from "@/resources/types/models/chage/was/trade/TradeModel";
import {Pagination} from "@/resources/types/models/common";
import {TRADES_HISTORIES_KEYS} from "@/react-query/was/trade/queryKeys";
import {TradeHistoryFilterDataStateSelector} from "@recoil/user/transcation/selectors";


const UserTransactionTradeHistoryList = ()=> {
  const userAccountInfo = useRecoilValue(UserAccountInfoState);

  const {acctId}             = useRecoilValue(UserAccountInfoState);
  const [dataLength, setDataLength] = useState(0);
  const [tradeHistoryFilter, setTradeHistoryFilter] = useRecoilState(TradeHistoryFilterDataStateSelector);

  const {data: tradeHistoryList} = useQuery<Pagination<TradeHistoryModel[]>>(
    TRADES_HISTORIES_KEYS.LIST(
      acctId,
      tradeHistoryFilter
    )
  );

  console.log('tradeHistoryList' , tradeHistoryList);
  useEffect(
    () => {
      if (!!tradeHistoryList?.record.length && tradeHistoryList?.record.length > 0) {
        setDataLength(tradeHistoryList.record.length);
      }
    },
    [tradeHistoryList]
  );


    return (

      <>
        {!!tradeHistoryList && dataLength > 0 ? (
          <>
            {tradeHistoryList.record.map((item, index) => {
              return (
                <>
                  <TradeHistoryItem key={index} item={item}/>
                </>
              );
            })}
          </>) : (
                 <TransactionNoUpdateItem />
        )}
      </>
    )
}

export default UserTransactionTradeHistoryList

이렇게 쓰는데 자꾸

react_devtools_backend_compact.js:2367 Warning: Each child in a list should have a unique "key" prop.

이런 에러가 생김 나는 key 줬는디..

?? 왜지

{orderHistoryList.record.map((item, index) => {
  return (
    <>
    	<OrderHistoryItem key={index} item={item}/>
    </>
  );
})}

이거랑

{orderHistoryList.record.map((item) => {
  return (
    <React.Fragment key={item.ordNo}>
    	<OrderHistoryItem item={item} />
    </React.Fragment>
  );
})}

무슨차이임?

GPT의 설명..

첫 번째 코드에서는 map 함수에 전달된 콜백 함수의 두 번째 매개변수로 index를 사용하여 key prop을 설정하고 있습니다. index는 각 항목의 인덱스를 나타내는 숫자 값입니다. 이 방식은 대개 고유한 식별자가 없을 때 사용됩니다. 그러나 주의해야 할 점은 index를 key로 사용할 때 문제가 발생할 수 있다는 것입니다. 리스트의 항목 순서가 변경되거나 항목이 추가/삭제되면 key가 변경되어 React의 효율적인 업데이트를 방해할 수 있습니다. 따라서 가능하면 고유한 속성을 key로 사용하는 것이 좋습니다.

두 번째 코드에서는 item 객체의 고유한 속성인 ordNo를 key prop으로 사용하고 있습니다. 이렇게 하면 item의 ordNo 값이 각 항목의 고유한 식별자로 사용되어 React가 효율적으로 업데이트를 수행할 수 있습니다. 이 방식은 항목들이 고유한 식별자를 가지고 있는 경우에 좋습니다.

따라서 두 코드의 차이점은 key prop으로 사용되는 값이 다르다는 것입니다. 첫 번째 코드에서는 인덱스를 사용하고, 두 번째 코드에서는 ordNo를 사용합니다. 두 번째 코드가 추천되는 방식이며, 가능하면 고유한 식별자를 key로 사용하는 것이 좋습니다.

{orderHistoryList.record.map((item) => {
  return (
    <React.Fragment key={item.id}>
      <OrderHistoryItem item={item} />
    </React.Fragment>
  );
})}

네, 첫 번째 방식으로 key로 인덱스를 사용하는 경우에는 리스트 항목의 순서가 변경되거나 항목이 추가/삭제될 때 문제가 발생할 수 있습니다. React는 key를 사용하여 가상 DOM의 업데이트를 최적화하는데, key가 변경되면 해당 항목을 완전히 재생성해야 합니다. 따라서 인덱스를 key로 사용할 경우, 리스트 항목의 순서가 변경되면 모든 항목이 재생성되고 업데이트 성능에 영향을 줄 수 있습니다.

또한, React는 key prop을 통해 각 항목을 고유하게 식별하므로, key prop을 사용하지 않거나 중복된 값을 사용하는 경우 경고 메시지가 발생합니다. 중복된 key는 React가 업데이트를 정확히 추적할 수 없게 되므로 문제가 발생할 수 있습니다.

따라서 리스트 항목에 고유한 식별자가 있다면 해당 식별자를 key로 사용하는 것이 좋습니다. 인덱스를 사용하는 대신에 고유한 속성을 key로 지정하면 React가 효율적인 업데이트를 수행할 수 있고, 중복된 key 문제를 피할 수 있습니다.


그렇군 일단은 해결..(?)

profile
냅다 써보는 공부의 흔적😇

0개의 댓글