Crea scroll infinito en React con un pequeño hook de IntersectionObserver, sin necesidad de paquetes, y mantén rápidos los feeds largos con virtualización. Demos en vivo y código para copiar.
Coloca un elemento centinela vacío después del último elemento y obsérvalo con IntersectionObserver. Cuando llegue a unos cientos de píxeles del viewport, pide la siguiente página y añádela. Un hook de veinte líneas lo hace sin librerías. Cuando la lista llegue a miles de filas, añade virtualización para que solo existan en el DOM las filas visibles.
Opciones de IntersectionObserver que importan para el scroll infinito
Las dos demos de abajo se ejecutan en esta página. La primera carga páginas de resultados falsos mientras desplazas su panel; la segunda recorre diez mil filas dibujando solo las veinte o así que puedes ver. Debajo está el código de cada una, listo para copiar.
No. IntersectionObserver está disponible en todos los navegadores principales desde 2019, y un hook pequeño cubre el caso habitual. Una librería de obtención de datos con utilidades de paginación integradas vale la pena cuando ya usas una para cachear peticiones.
La virtualización renderiza solo las filas dentro de la ventana visible más un pequeño margen, colocadas dentro de un espaciador con la altura total de la lista. Recurre a ella cuando el DOM tenga miles de filas y el desplazamiento o la escritura empiecen a ir lentos. @tanstack/react-virtual y su hook useVirtualizer son una opción habitual.
Los rastreadores de los buscadores no se desplazan como las personas, así que el contenido que solo aparece al desplazarse puede no verse nunca. Respalda el feed con URLs paginadas reales como ?page=2 que carguen por sí solas, y enlázalas.
Normalmente el efecto vuelve a crear el observer en cada render porque el callback cambia de identidad, o la primera página es demasiado corta para sacar el centinela de la pantalla. Guarda el callback más reciente en una ref y asegúrate de que cada página ocupe más que el viewport.
Devuelve una ref para el centinela. El onLoadMore más reciente se guarda en una ref para que el observer se cree una vez por cada cambio de enabled, no en cada render.
La marca de carga evita las peticiones dobles, y hasMore desactiva el observer al final.
Instálalo con npm install @tanstack/react-virtual. La caja exterior se desplaza, la interior es tan alta como toda la lista y cada fila visible se coloca en su sitio con translateY.
Solo se renderizan las filas cercanas a la ventana visible. estimateSize es la altura de la fila en píxeles.
Demo: un feed que carga mientras te desplazas
Desplázate dentro del panel. Llega una página nueva de diez elementos cada vez que el centinela entra en el rango, hasta ocho páginas.
Demo del feed
Publicación {n}
Cargando...
Has llegado al final.
Cargar más
{items} elementos, página {page} de {last}
Reiniciar
Demo: 10,000 filas, solo se renderizan las visibles
Desplaza la lista y observa qué pocas filas existen realmente en la página en cada momento.
Demo de lista virtual
Fila {n}
Renderizando {shown} de {total} filas
Empieza gratis · Sin tarjeta de crédito