Feed infinito
Un feed que nunca termina tiene que pedir datos mientras el usuario mira: lo bastante pronto para que la siguiente publicación ya esté ahí, con algo que mostrar mientras una página llega o si ha fallado, y sin dejar ninguna petición en marcha cuando el feed ya no está.
Pruébalo
Todas las versiones importan ./api, que sustituye a tu backend: fetchPosts(page, signal) devuelve una página de publicaciones y se detiene cuando la señal se aborta. Cámbialo por una llamada a tu API y quita failNextRequest, que solo controla el interruptor de fallo de la demo.
import { createSignal } from '@reelkit/core';
import { cdnUrl } from '@reelkit/example-data';
// Stands in for your backend. The recipe only relies on the signature of
// `fetchPosts`: a page number in, a page of posts out, cancellable through an
// AbortSignal.
export interface Post {
id: string;
title: string;
image: string;
}
const kPageSize = 6;
const kDelayMs = 800;
const kImages = Array.from(
{ length: 9 },
(_, i) => `samples/images/image-${String(i + 1).padStart(2, '0')}.jpg`,
);
/**
* Demo switch: while on, the next request fails, so the error slide can be
* seen. A signal, so the switch shows when a request has used it up. Only the
* demo on this page uses it: delete it, and the `@reelkit/core` import with
* it, when you replace `fetchPosts` with your API.
*/
export const failNextRequest = createSignal(false);
export function fetchPosts(page: number, signal: AbortSignal): Promise<Post[]> {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
if (failNextRequest.value) {
failNextRequest.value = false;
reject(new Error('The feed could not be loaded.'));
return;
}
resolve(
Array.from({ length: kPageSize }, (_, i) => {
const n = page * kPageSize + i;
return {
id: `post-${n}`,
title: `Post ${n + 1}`,
image: cdnUrl(kImages[n % kImages.length]),
};
}),
);
}, kDelayMs);
signal.addEventListener(
'abort',
() => {
clearTimeout(timer);
reject(signal.reason);
},
{ once: true },
);
});
}Los medios de ejemplo solo funcionan en reelkit.dev
cdnUrl crea enlaces a cdn.reelkit.dev, que solo sirve sus archivos a los sitios de ReelKit. En tu app esas imágenes no cargan, así que apunta image a tus propios medios antes de copiar este archivo.
Desliza hacia arriba o pulsa ↓: una página nueva llega tres publicaciones antes del final. Pulsa "Fail next request" para ver el slide de error y su Retry.
Por qué funciona
- Crece el recuento, no los slides.
countes el número de publicaciones más uno, y en el DOM solo hay tres slides a la vez, así que un feed de miles cuesta lo mismo que uno de diez. Consulta la virtualización. - El último slide muestra el estado. El slide extra tras las publicaciones muestra "Loading…" mientras llega una página y el error con Retry cuando ha fallado, así el usuario nunca desliza hacia la nada. Es un caso más del itemBuilder, que dibuja lo que represente cada índice.
- Pide por adelantado, desde el cambio de slide.
afterChangepide la siguiente página cuando el usuario está a tres publicaciones del final. Una página fallida espera a Retry, así que deslizar adelante y atrás no repite una petici ón que falla. El callback aparece con los demás eventos para React, Vue y Angular. - Las claves siguen a las publicaciones.
keyExtractordevuelve el id de cada publicación, así un slide conserva su elemento cuando llega una página detrás en vez de reconstruirse desde su índice. Es una prop en React, Vue y Angular por igual. - Las imágenes cargan antes que su slide. Un slide más abajo aún no está montado, porque solo lo está el rango visible, como explica la virtualización. Por eso las imágenes de cada página nueva se piden en cuanto llega la página y salen de la caché del navegador cuando su slide se monta.
- Teclas y rueda apagadas a propósito.
enableNavKeysescucha en toda la ventana yenableWheelretiene el scroll de la página mientras el puntero está sobre el feed. Ambos encajan en un feed a pantalla completa y estorban en una página que lo contiene, como esta, así que aquí quedan apagados y dos botones llaman aprev()ynext()de la API de Reel. Deslizar funciona igual. - Nada sobrevive al feed. Cada petición lleva un
AbortControllerque se aborta cuando el feed se desmonta, así una respuesta tardía nunca escribe en un feed que ya no está.
Siguientes pasos
- De la cuadrícula al reproductor - abre el reproductor a pantalla completa desde una cuadrícula de miniaturas y vuelve a donde estabas
- Guía del framework - cada prop y patrón de Reel detrás de esta recetaGuía del framework - cada prop y patrón de Reel detrás de esta recetaGuía del framework - cada prop y patrón de Reel detrás de esta receta