Imágenes y otros medios
Después de configurar Reactive Data Client para obtener datos estructurados, quizás quieras incorporar también algunas cargas de medios para aprovechar suspense y el soporte del modo concurrente.
Almacenar un ArrayBuffer
Resource y Entity no deben usarse en este caso, ya que ambos representan estructuras de mapa string -> valor. En su lugar, definiremos nuestro propio Endpoint simple.
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
- useCache
- JS/Node
// photo is typed as ArrayBuffer
const photo = useSuspense(getPhoto, { userId });
// photo will be undefined if the fetch hasn't completed
// photo will be ArrayBuffer if the fetch has completed
const photo = useCache(getPhoto, { userId });
// photo is typed as ArrayBuffer
const photo = await getPhoto({ userId });
Solo imágenes
En muchos casos sería útil suspender la carga de elementos costosos como las imágenes usando suspense. Esto resulta especialmente potente con el patrón fetch as you render en modo concurrente.
@data-client/img ofrece un componente <Img /> que suspende, así como un endpoint getImage para precargar.
Instalación
- NPM
- Yarn
- pnpm
- esm.sh
yarn add @data-client/img
npm install --save @data-client/img
pnpm add @data-client/img
<script type="module">
import * from 'https://esm.sh/@data-client/img';
</script>
Uso
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>
);
}
Precarga
Ten en cuenta que esto encadenará las peticiones: hay que esperar a que se resuelva el usuario antes de que pueda comenzar la petición de la imagen. Si la URL de la imagen es determinista a partir de los mismos parámetros, podemos iniciar esa petición al mismo tiempo que la del usuario:
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>
);
}
Al usar el patrón fetch as you render en modo concurrente, usa Controller.fetch() con el Endpoint getImage
para precargar la imagen.