용량이 큰 이미지들을 받아올때, 이미지 요소 각각 다운로드 되는 시간이 다르기때문에 이미지가 순차적으로 보여졌고, 이는 UX적으로 좋지 않은 영향을 끼칠 수 있기 때문에 모든 이미지가 로드된 뒤 element가 보여질수 있도록 Promise.all
을 사용해서 구현했다.
Promise.all() 메서드는 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후, 혹은 프로미스가 주어지지 않았을 때 이행하는 Promise를 반환합니다. 주어진 프로미스 중 하나가 거부하는 경우, 첫 번째로 거절한 프로미스의 이유를 사용해 자신도 거부합니다.
출처 : MDN - Promise.all()
MDN에 나와있는 설명처럼, Promise.all 을 사용하면 모든 배열 요소를 순회해서 resolve가 끝나면 promise를 반환하기 때문에, 모든 이미지가 로드되는 시점에 state를 업데이트하는 방식으로 구현이 가능하다.
const [items, setItems] = useState([]);
useEffect(() => {
if (items.length > 0) {
const loadImagePromises = items.map(item => {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = {이미지 경로};
img.onload = resolve;
img.onerror = reject;
});
});
Promise.all(loadImagePromises).finally(() => {
setItemsReady(true); // 모든 이미지 로딩이 완료되었을때 상태 업데이트
});
}
}, [items]);
먼저 배열 요소를 순회해 new Promise
생성자를 통해 각 요소에 맞는 img를 생성하고,
Promise.all 로 모든 이미지가 resolve 되고 나면 finally callback으로 로딩 state를 true로 바꿔주었다.
이런 방법을 통해 스켈레톤 UI를 넣어주는 등, 이미지 로딩 처리가 가능하다!