Volver a la página principal
martes 24 septiembre 2024
26

Cómo crear un Infinite Scroll en React usando Intersection Observer

El infinite scroll (o desplazamiento infinito) es una técnica que carga más contenido a medida que el usuario se desplaza hacia abajo en una página web, ofreciendo una experiencia fluida y sin interrupciones. En lugar de hacer clic en un botón para cargar más contenido, el infinite scroll carga automáticamente el siguiente lote de datos cuando el usuario llega al final de la página. Esta técnica es popular en aplicaciones que manejan grandes cantidades de datos, como redes sociales, tiendas en línea o portales de noticias.

¿Qué es Intersection Observer?

La API de Intersection Observer nos permite observar un elemento del DOM y detectar cuándo entra o sale del viewport. Esto es extremadamente útil para casos como el lazy loading de imágenes, el seguimiento de la visibilidad de anuncios o, en nuestro caso, cargar más elementos en una lista cuando el usuario se acerca al final.

Beneficios de usar Intersection Observer

  • Rendimiento: A diferencia de soluciones basadas en eventos de scroll, Intersection Observer es más eficiente porque se activa solo cuando es necesario, en lugar de estar escuchando el evento de desplazamiento en cada movimiento del usuario.
  • Simplicidad: Facilita la lógica de detección del final de una lista sin depender de cálculos manuales de posición.
  • Soporte nativo: Al ser una API nativa, no requiere dependencias adicionales para funcionar en la mayoría de los navegadores modernos.

Paso a paso: Implementar Infinite Scroll en React

Vamos a crear un ejemplo sencillo de infinite scroll en el que cargaremos una lista de elementos en lotes. Cada vez que el usuario llegue al final de la lista, se cargará un nuevo lote de datos.

1. Configurar un proyecto de React

Si aún no tienes un proyecto de React, puedes crearlo con:

npx create-react-app infinite-scroll
cd infinite-scroll

Una vez creado el proyecto, borra los archivos que no vayas a usar (como logo.svg y otros archivos innecesarios) y asegúrate de que el archivo App.js esté limpio para empezar a trabajar.

2. Crear el componente de lista con Infinite Scroll

Vamos a crear un componente de lista que cargará más elementos a medida que el usuario se desplace hacia abajo.

Estructura del componente:

1. Estado: Necesitaremos manejar dos estados, uno para la lista de elementos y otro para determinar si estamos cargando más datos.

2. useEffect: Este hook se usará para manejar el efecto secundario de observar el elemento.

3. Intersection Observer: Utilizaremos esta API para observar el último elemento de la lista y cargar más datos cuando sea visible.

Código del componente

import React, { useState, useEffect, useRef } from "react";

const InfiniteScroll = () => {
  const [items, setItems] = useState(Array.from({ length: 20 }));
  const [isFetching, setIsFetching] = useState(false);
  const observerRef = useRef(null);

  // Simulación de una función para cargar más datos
  const fetchMoreData = () => {
    setTimeout(() => {
      setItems((prevItems) => [
        ...prevItems,
        ...Array.from({ length: 20 }), // Agregamos 20 nuevos elementos
      ]);
      setIsFetching(false);
    }, 1500);
  };

  // Intersection Observer
  useEffect(() => {
    if (isFetching) return;

    const observer = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting) {
        setIsFetching(true);
      }
    });

    if (observerRef.current) {
      observer.observe(observerRef.current);
    }

    return () => {
      if (observerRef.current) {
        observer.unobserve(observerRef.current);
      }
    };
  }, [isFetching]);

  useEffect(() => {
    if (!isFetching) return;
    fetchMoreData();
  }, [isFetching]);

  return (
    <div>
      <h1>Infinite Scroll con Intersection Observer</h1>
      <ul>
        {items.map((_, index) => (
          <li key={index} style={{ padding: "20px", border: "1px solid black" }}>
            Elemento {index + 1}
          </li>
        ))}
      </ul>
      <div ref={observerRef} style={{ height: "20px" }} />
      {isFetching && <p>Cargando más elementos...</p>}
    </div>
  );
};

export default InfiniteScroll;

Explicación del código

1. Estado items: Este estado contiene la lista de elementos que se van a renderizar. Inicialmente, llenamos esta lista con 20 elementos ficticios usando Array.from({ length: 20 }).

2. Estado isFetching: Este estado es un flag que indica si estamos en el proceso de cargar más datos.

3. observerRef: Usamos un ref para referenciar el último elemento en la lista, el cual será observado por la API de Intersection Observer.

4. IntersectionObserver:

  • Creamos una instancia de IntersectionObserver dentro del hook useEffect.
  • Observamos si el elemento referenciado por observerRef entra en el viewport. Si es así, activamos el estado isFetching para indicar que debemos cargar más datos.
  • Cuando isFetching es true, llamamos a fetchMoreData que simula la carga de nuevos datos agregando 20 más elementos a la lista.

3. Ajustes y mejoras

Controlar la recarga de datos

Para evitar que el infinite scroll siga cargando datos indefinidamente, podrías agregar una condición de límite de elementos:

const [hasMore, setHasMore] = useState(true);

const fetchMoreData = () => {
  if (items.length >= 100) {
    setHasMore(false);
    return;
  }
  // Lógica de carga de más datos
};

De esta manera, solo cargaremos más elementos mientras el total sea menor que un valor específico, como 100 en este caso.

Mejora visual

Puedes agregar un spinner o una animación mientras se cargan nuevos elementos, en lugar del simple texto "Cargando más elementos...".

{isFetching && hasMore && <div className="spinner">Cargando...</div>}

Estilos CSS básicos

Agrega algunos estilos básicos para que la lista se vea mejor:

ul {
  list-style: none;
  padding: 0;
}

li {
  margin-bottom: 10px;
  background: #f0f0f0;
  padding: 20px;
  text-align: center;
}

.spinner {
  text-align: center;
  padding: 10px;
}

4. Conclusion

El uso de Intersection Observer para implementar un infinite scroll en React es una solución eficiente y moderna para cargar más contenido a medida que el usuario se desplaza. La API nativa se encarga de observar el último elemento visible en la lista, evitando la necesidad de calcular manualmente cuándo estamos al final del scroll, lo cual mejora el rendimiento de nuestra aplicación.

Este enfoque es ideal para aplicaciones que manejan grandes cantidades de datos o listas dinámicas. Recuerda que siempre puedes personalizar y optimizar la lógica según tus necesidades, controlando la cantidad de datos cargados, el tiempo de espera, o añadiendo otras características como filtros o paginación dinámica.

¿Listo para poner en marcha un scroll infinito en tu aplicación? ¡Espero que esta guía te haya sido de ayuda! 😃😃

Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer