React Suspense와 함께 활용해 image 주소로 직접 fetch 요청을 보내 blob 객체로 이미지를 불러오는 방법도 있음. 하지만, 이 방법을 이용하면 CORS 오류를 해결해야 하고, 캐시된 이미지를 불러올 때는 스켈레톤 화면이 보이지 않는 문제도 있는 한계가 있음.
2. Image onLoad 이벤트 활용
<img> 요소의 onLoad 이벤트를 활용해 아직 로드되지 않았을 때는 스켈레톤을 보여주고, 로드가 완료되었을 때 State를 변경해 원래 이미지를 보여주는 방식을 이용할 수 있음. 한편, 이미지를 불러올 때 오류가 발생할 수 있는데 계속 스켈레톤을 보여주는 것보다는 기본 이미지를 보여주는 것으로 onError 이벤트를 활용할 수 있음.
이미지 로딩 스켈레톤으로 나타내기
1. React Query, React Suspense 활용
2022.10.01 - [React] - React Suspense 사용하기(with. React-Query)
React Suspense와 함께 활용해 image 주소로 직접 fetch 요청을 보내 blob 객체로 이미지를 불러오는 방법도 있음. 하지만, 이 방법을 이용하면 CORS 오류를 해결해야 하고, 캐시된 이미지를 불러올 때는 스켈레톤 화면이 보이지 않는 문제도 있는 한계가 있음.
2. Image onLoad 이벤트 활용
<img> 요소의 onLoad 이벤트를 활용해 아직 로드되지 않았을 때는 스켈레톤을 보여주고, 로드가 완료되었을 때 State를 변경해 원래 이미지를 보여주는 방식을 이용할 수 있음. 한편, 이미지를 불러올 때 오류가 발생할 수 있는데 계속 스켈레톤을 보여주는 것보다는 기본 이미지를 보여주는 것으로 onError 이벤트를 활용할 수 있음.
A. Skeleton을 Props로 전달했을 때
스켈레톤 컴포넌트를 이미지 컴포넌트 내부에 넣는 대신 Props로 넘겨서 재사용성을 극대화하는 방법은 어떨까?
현재 불러온 페이지 이전의 ProductItem 컴포넌트의 skeleton 속성이 변경되어 재렌더링될 필요가 없는 이전 ProductItem 컴포넌트까지 재렌더링되어 100여개의 ProductItem을 렌더링하는 시간이 33ms나 걸림.
왜 이전 ProductItem까지 skeleton Props가 변경되는 걸까?
ProductList 컴포넌트에서 ProductItem을 렌더링할 때, Props로 전달하는 <ProductItemSkeleton />는 React.createElement() 메서드로 생성되기 때문에 이전 ProductItem 컴포넌트의 skeleton Props가 달라지게 됨.(새로운 객체를 생성해 주소값이 달라졌으므로) JSX 문법인 <Component />는 Component()를 표현한 것이라고 생각하면 간단함.
따라서, ProductItemSkeleton를 Props로 넘겨주는 것보다 ProductItem 내부에 직접 넣어주는 것이 좋음.
B. Skeleton을 컴포넌트 내부에 넣었을 때
A에서와 달리 이번에는 이전에 렌더링되었던 ProductItem이 재렌더링되지 않기 때문에 전체적인 렌더링 시간도 줄어들었음을 확인할 수 있음.
[참고]
React onLoad event on image tag is not getting called when using conditional render
How to detect when a image is loaded, that is provided via props, and change state in React?
'JavaScript > React' 카테고리의 다른 글