yamoo9 / likelion-FEQA

질문/답변 — 프론트엔드 스쿨, 멋사
29 stars 9 forks source link

[LAB-4] Objects are not valid as a React child 에러 원인을 알고 싶습니다 #227

Closed SeoMiYoung closed 1 year ago

SeoMiYoung commented 1 year ago

질문 작성자

서미영

문제 상황

안녕하세요. 현재 저는 마켓칼리에서 image 위의 사진에 사용자가 제목(title)부분에 제목을 입력하고, 내용(textarea)부분에 내용을 입력한 후, '등록'버튼을 누르면, 파이어스토어에 다음과 같이 데이터들이 쌓이게 구현하였습니다.

다음 사진은 현재 파이어스토어에 데이터들이 저장된 상태입니다. image

저는 이 데이터들을 가져다가 출력하고 싶었습니다. 만든 유틸함수인, firebase/firestore/useDetailFireStore.js에서는 컬렉션 안에 있는 객체형태의 document들을 배열(dataArr)에 담아서, dataState로 반환합니다. 그래서, 위에 사진과 같이 현재 컬렉션에 document가 4개가 담겼다면, image 이렇게 담기게 됩니다.

저는 이 배열을 상품문의를 구현하기 위한 파일인, ProductInquiry.jsx에서 dataState를 받아와서 이 배열을 사용했습니다. ProductInquiry.jsx의 112번째줄에서 { dataState ? <ProductInquiryHandle data={dataState} /> : null } 이렇게 작성하여, 빈배열이 아니면, <ProductInquiryHandle data={dataState} />를 넣어주기로 했습니다.

ProductInquiryHandle/ProductInquiryHandle.jsx를 보시면, map함수를 통해, 배열안의 객체들을 하나씩 순회하며, return을 통해 반환하는 형식으로 코드를 짠 걸 확인할 수 있습니다.

그러나 여기서 희안한 점을 발견했는데요, image 이런식으로 return을 하면, image 이렇게(노란색으로 표시한 곳) 제가 원하는대로 데이터들이 title과 내용이 출력되는 걸 확인할 수 있습니다.

그러나, 저는 단순하게 저렇게 출력하고 싶은게 아니라, 공용 컴포넌트인 아코디언을 사용해서 출력하고 싶어서, return안의 내용을 다음과 같이 바꿨습니다. image 이렇게 내보냈을 경우, image 위와 같은 에러가 뜹니다.

사실 저는 처음에 제가 작성한 return과 두번째로 작성한 return이 코드만 길어졌지, 작성하는 방식은 차이가 없다고 생각했는데, 왜 두번째의 경우 위와 같은 에러가 발생했을까요?

오랜시간 고민했으나 해결되지 않아서 질문을 올립니다 ㅠㅠ 답변해주시면 감사하겠습니다.

프로젝트 저장소 URL

https://github.com/SeoMiYoung/project-repo

branch: feat/#96

환경 정보

운영체제 정보: 윈도우 Node.js 정보: v18.14.0

yamoo9 commented 1 year ago

문제 원인

Console에 출력된 오류 메시지가 원인을 잘 알려 줍니다.

Objects are not valid as a React child (found: object with keys {seconds, nanoseconds}). If you meant to render a collection of children, use an array instead.

오류 내용을 살펴보면 객체(Object) 타입은 React 자식으로 유효하지 않습니다. 그리고 자식으로 포함될 데이터 중 객체 타입을 찾았고 내부에 seconds, nanoseconds 속성을 포함한 객체입니다.

문제 해결

질문에 포함된 아래 코드에서 날짜(item.date) 정보가 객체입니다.

<AccordionItem index={accordionIndex} width="1024px">
  <div>
    <div>{item.title}</div>
    <div>{item.writer}</div>
    <div>{item.date}</div>
    <div>{item.state}</div>
  </div>
  <div>
    <span>{item.textarea}</span>
  </div>
</AccordionItem>

Firestore에 저장된 날짜 정보는 Timestamp 타입의 객체입니다. 공식 문서를 보면 Timestamp 객체는 seconds, nanoseconds 속성을 가지는 것을 알 수 있습니다.

그리고 Timestamp 객체는 JavaScript 날짜 객체인 Date로 변환해주는 toDate 메서드를 가집니다.

image

앞서 살펴본 것처럼 React는 객체 타입을 자식으로 포함할 수 없죠. 그러므로 Timestamp → Date → String으로 타입을 변환해야 합니다. 🙂

<div>{item.date.toDate().toLocaleDateString()}</div>

그러면 더 이상 객체 타입이 아니므로 정상적으로 React 자식으로 렌더링 될 것입니다. 😃

참고

date-fns, moment.js와 같은 라이브러리를 사용해 날짜를 커스텀 포멧팅 할 수도 있습니다.

SeoMiYoung commented 1 year ago

와.,, 에러의 의미를 알긴 알았는데, Timestamp에 관련된 에러인지는 상상도 못했네요. 참고해서 코드를 잘 고쳐보도록 하겠습니다. 답변 정말 감사합니다!!

SeoMiYoung commented 1 year ago

선생님 ㅠㅠ

return (
            // eslint-disable-next-line react/jsx-key
            <AccordionItem index={accordionIndex} width="1024px">
              <div className={styles.handleDivWrapper}>
                <div className={styles.writingTitle}>{item.title}</div>
                <div className={styles.writer}>{item.writer}</div>
                <div className={styles.reportingDate}>{item.date.toDate().toLocalDateString()}</div>
                <div className={styles.answerStatus}>{item.state}</div>
              </div>
              <div>
                <span>{item.textarea}</span>
              </div>
            </AccordionItem>
          )

이렇게 return안의 코드를 수정해봤는데ㅠㅠ
image 이런 타입에러가 발생합니다 ㅠㅠ toData.toLocalDateString()이게 함수가 아니다~라는 것 같은데, 혹시 저 함수를 사용하려면 뭘 추가해주거나, 함수라고 타입을 지정해줘야되거나 해야되는건가요??

yamoo9 commented 1 year ago

@SeoMiYoung 님

toLocaleDateString 메서드 입니다. ^^

item.data.toDate().toLocaleDateString()

아래 첨부된 이미지를 보면 Firestore Timestamp, Date, string 순으로 출력된 것을 볼 수 있습니다.

image
SeoMiYoung commented 1 year ago

야무쌤...진짜 자꾸 질문해서 죄송한데요 ㅠㅠ 혹시

들어가셔서 확인해주실 수 있으신가요..? ㅠㅠ <div className={styles.reportingDate}>{item.date.toDate().toLocalDateString()}</div> 피드백 주신대로 했는데, 자꾸 에러가 해결되지 않아서요 ㅠㅠㅠ <div className={styles.reportingDate}>{item.date.toDate().toLocalDateString()}</div> 이 부분에만 문제 있는게 확실한게, 이 한줄을 지우면 전혀 문제없이 돌아가거든요..ㅠㅠ

확인해주시면 감사합니다 ㅠㅠ

yamoo9 commented 1 year ago
  • ProductInquiryAccordion

@SeoMiYoung 님 ^^;; https://github.com/yamoo9/likelion-FEQA/issues/227#issuecomment-1483720980 답변에서 말씀드렸듯이 메서드 이름이 잘못 되었어요. toLocalDateString이 아니고, toLocaleDateString 입니다.

SeoMiYoung commented 1 year ago

헐.....제가 왜 이걸.....헐.....진짜...왜 눈에 안보였죠..?ㅠㅠ 와..진짜...이런것가지고 여러번 질문해서 죄송합니다 ㅠㅠㅠㅠㅠ!! 덕분에 이제 똑똑히 기억할 수 있을 것 같아요 ㅠㅠ흑흑 진짜 진짜 도움주셔서 감사드려요!!!!ㅠㅠ