# Images and other Media

After setting up Reactive Data Client for structured data fetching, you might want to incorporate
some media fetches as well to take advantage of suspense and [concurrent mode support](https://dataclient.io/docs/guides/render-as-you-fetch.md).

## Storing ArrayBuffer

[Resource](https://dataclient.io/rest/api/resource.md) and [Entity](https://dataclient.io/rest/api/Entity.md) should not be used in this case, since they both represent
string -> value map structures. Instead, we'll define our own simple [Endpoint](https://dataclient.io/rest/api/Endpoint.md).

```typescript
import { Endpoint } from '@data-client/rest';

export const getPhoto = new Endpoint(async ({ userId }: { userId: string }) => {
  const response = await fetch(`/users/${userId}/photo`);
  const photoArrayBuffer = await response.arrayBuffer();

  return photoArrayBuffer;
});
```

**useSuspense**

```tsx
// photo is typed as ArrayBuffer
const photo = useSuspense(getPhoto, { userId });
```

**useCache**

```tsx
// photo will be undefined if the fetch hasn't completed
// photo will be ArrayBuffer if the fetch has completed
const photo = useCache(getPhoto, { userId });
```

**JS/Node**

```tsx
// photo is typed as ArrayBuffer
const photo = await getPhoto({ userId });
```

## Just Images

In many cases, it would be useful to suspend loading of expensive items like
images using suspense. This becomes especially powerful [with the fetch as you render](https://dataclient.io/docs/guides/render-as-you-fetch.md) pattern in concurrent mode.

[@data-client/img](https://www.npmjs.com/package/@data-client/img) provides use with `<Img />` component that suspends, as well as `getImage` endpoint to prefetch.

## Installation

```bash
npm install @data-client/img
```

## Usage

```tsx title="Profile.tsx"
import React, { ImgHTMLAttributes } from 'react';
import { useSuspense } from '@data-client/react';
import { Img } from '@data-client/img';
import { UserResource } from './resources/User';

export default function Profile({ username }: { username: string }) {
  const user = useSuspense(UserResource.get, { username });
  return (
    <div>
      <Img
        src={user.img}
        alt="React Logo"
        style={{ height: '32px', width: '32px' }}
      />
      <h2>{user.fullName}</h2>
    </div>
  );
}
```

#### Prefetching

Note this will cascade the requests, waiting for user to resolve before
the image request can start. If the image url is deterministic based on the same parameters, we can start that request at the same time as the user request:

```tsx title="Profile.tsx"
import React, { ImgHTMLAttributes } from 'react';
import { useSuspense, useFetch } from '@data-client/react';
import { Img, getImage } from '@data-client/img';
import { UserResource } from './resources/User';

export default function Profile({ username }: { username: string }) {
  const imageSrc = `/profile_images/${username}}`;
  useFetch(getImage, { src: imageSrc });
  const user = useSuspense(UserResource.get, { username });
  return (
    <div>
      <Img
        src={imageSrc}
        alt="React Logo"
        style={{ height: '32px', width: '32px' }}
      />
      <h2>{user.fullName}</h2>
    </div>
  );
}
```

When using the [fetch as you render](https://dataclient.io/docs/guides/render-as-you-fetch.md) pattern in concurrent mode, [Controller.fetch()](https://dataclient.io/docs/api/Controller.md#fetch) with the `getImage`
[Endpoint](https://dataclient.io/rest/api/Endpoint.md) to preload the image.
