React Uncaught TypeError: Cannot read properties of undefined
Uncaught TypeError : Cannot read properties of undefined
이 에러가 나타나는 이유에 대해서 정리해본다.
이유
1. 데이터를 받아올 때 state의 초기 값이 어떤 데이터 타입인지 명시하지 않은 경우이다.
// 데이터 타입을 명시하지 않은 예시문
const [data, setData] = useState();
// 데이터 타입을 명시한 예시문
const [data, setData] = useState([]);
2. 새로고침을 눌렀거나 api 데이터가 담긴 state가 변경되었을 때이다.
a. 부모 컴포넌트에서 이런 코드를 작성하고 자식 컴포넌트로 데이터를 넘겨줬을 것이다
목 데이터를 받아와서 filmsData라는 state에 저장하는 코드이다.
const Detail = () => {
const [isLoading, setIsLoading] = useState(true);
const [filmsData, setFilmsData] = useState([]);
useEffect(() => {
fetch("data/detailData.json")
.then(res => res.json())
.then(setFilmsData)
.then(() => setIsLoading(false));
}, []);
return (
<div>
{isLoading && <SkeletonUi />}
{!isLoading && (
<div className="detailPage">
<ThumbnailImage filmsData={filmsData} />
<Information />
<DescriptionCard />
</div>
)}
</div>
);
};
export default Detail;
b. 자식 컴포넌트에서는 데이터를 이렇게 받는다.
const ThumbnailImage = ({ filmsData: { films } }) => {
if (!films) return;
return (
<div className="thumbnailImage">
<img className="coverImage" src={films.image_url} alt="poster_image" />
{/* <ul className="rankingInfoList" /> */}
</div>
);
};
데이터를 받기만 할때는 어떤 문제도 없다! 하지만 새로고침을 하거나 목 데이터의 데이터를 수정한 순간?
Uncaught TypeError : Cannot read properties of undefined
깨끗한 하얀 화면만이 보일 것이며, 콘솔 창에 이런 에러메세지가 출력 될 것이다.
이것에 대해 설명해본다.
1. 새로고침을 눌렀다. 그럼 모든 컴포넌트가 다시 마운트 된다. 당연히 이전에 useEffect로 실행해서 저장한 데이터도 초기화된 직후다.
2. 이때 useEffect는 실행되지 않는다. hook의 생명주기상 지금 바로 실행되진 않는다.
3. detail 컴포넌트는 isLoading이라는 state의 초기 값이 true 이기 때문에 스켈레톤 컴포넌트가 렌더링 된다.
4. 부모 컴포넌트에서 스켈레톤 컴포넌트가 렌더링 됬기 때문에 모든 자식 컴포넌트는 그려지지 않는다.
5. 에러가 없다면 useEffect가 실행된다.
6. useEffect가 실행되고 그 안에 들어있는 함수들(setFilmsData, setIsLoading)에 의해 state 값이 변경되어 다시 렌더링이 시작된다. 이때 thumbnail 컴포넌트는 전달받은 데이터가 이제 존재하기 때문에 렌더링 된다.
7. isLoading의 값이 false로 변경되면서 스켈레톤 컴포넌트가 아니라 실제 데이터가 반영된 ui를 화면에 그려준다.
이제야 도현님의 숙제가 끝났다. 이걸 풀었다고 생각한 저번에는 undefined가 객체기 때문에 그런줄 알았다. 그런데 크나큰 오해였고, 이번에 확실히 공부하게되었다. 왜 undefined가 출력되는지 확실히 이해가 가고 어떤 원리로 리액트가 굴러가는지 이해가 갔다. 그리고 왜 조건부 렌더링을 할때 맨 앞 조건에 받아온 데이터가 들어있는 state를 적으면 안되는지도 이해가 갔다 .
하지만 이해가 갔더라도 또 이상한 문제를 만나겠지 ㅠㅠ
