> For the complete documentation index, see [llms.txt](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/dev_note/react-hook-in-action/suspense.md).

# Suspense와 이미지 적재하기

```typescript
const imagePromise = new Promise((resolve) => {
  const img = new Image();  // 새 이미지 객체 생성
  img.onload = () => rseolve(img) // 이미지 적재가 끝나면 프로미스 해소
  img.src = "path/to/image/image.png" // 소스 지정해 이미지 적재 시작
})
```

* 캐시를 위해 리엑트 쿼리를 사용!?
* 동일한 src를 사용하는 여러 Img 컴포넌트를 사용해도 이미지를 여러 번 적재하지 않음
* 리엑트 쿼리는 캐싱된 Image 객체를 반환
  * 이미지 자체는 브라우저에 의해 캐싱됨

```typescript
const Img = ({src, alt, ...props}) => {
  const {data: imgObject} = useQuery(
    src,
    () => new Promise((resolve) => {
      const img = new Image();
      img.onload = () => resolve(img);
      img.src = src;
    }),
    {suspense: true}
  )
 
  return <img src={imgObject.src} alt={alt} {...props} /> 
}
```

* Img와 Suspense를 사용하는 컴포넌트 예시

```typescript
import { Suspense } from 'react';
import { useQuery } from 'react-query';

const Avatar = ({src, alt, fallbackSrc, ...props}) => {
  return {
    <div>
      <Suspense
        fallback={<img src={fallbackSrc} alt="Fallback Avatar" />}
      >
        <Img src={src} alt={alt} {...props} />
      </Suspense>
    </div>
  }
}
```

{% hint style="success" %}
페이지의 head 엘리먼트에서 **`rel='prefetch`**'와 함께 link 엘리먼트를 추가해서 폴백 이미지를 미리 적재할 수도 있다.
{% endhint %}

### 리엑트 쿼리를 사용해 이미지나 데이터를 미리 적재하는 방법

* **`queryClient.prefetchQuery`**
  * 메서드를 호출해서 가능한 빨리 리소스를 적재하기
* 폭포수 방식의 데이터 적재(한 자원이 다 적재된 후에 다음 자원 적재를 시작하는 방식)을 최대한 피해라.
