Solución al Problema del Resize Observer en React

El uso del ResizeObserver en React puede ser un desafío, especialmente cuando se trata de calcular el ancho de los elementos y desplegar los enlaces visibles. En este artículo, abordaremos cómo implementar una solución efectiva para manejar el resize de componentes, asegurando que el número de enlaces visibles se ajuste correctamente sin causar problemas de rendimiento.

¿Qué es el Resize Observer?

ResizeObserver es una API que permite a los desarrolladores observar los cambios de tamaño de un elemento del DOM. En el contexto de React, esto es útil para manejar dinámicamente el diseño de componentes en respuesta a cambios en la ventana o cambios de tamaño de contenedores.

Implementación de una Solución Eficaz

La clave para implementar una solución eficaz es evitar llamadas redundantes a la función de cálculo de ancho de los elementos. A continuación se presenta un ejemplo de cómo se puede realizar esta implementación, utilizando referencias y efectos en React.

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

const MyComponent = ({ links }) => {
    const navContainerRef = useRef(null);
    const dummyContainerRef = useRef(null);
    const [visibleLinks, setVisibleLinks] = useState([]);
    const [hiddenLinks, setHiddenLinks] = useState([]);

    const calculateLinks = () => {
        if (!navContainerRef.current || !dummyContainerRef.current) return;

        const containerWidth = navContainerRef.current.offsetWidth - 20;
        const dummyItems = dummyContainerRef.current.children;
        const itemWidths = Array.from(dummyItems).map((item) => item.offsetWidth);

        let totalWidth = 0;
        let visibleCount = 0;

        for (let i = 0; i < links.length; i++) {
            if (totalWidth + itemWidths[i] <= containerWidth) {
                totalWidth += itemWidths[i];
                visibleCount++;
            } else {
                break;
            }
        }

        const newVisibleLinks = links.slice(0, visibleCount);
        const newHiddenLinks = links.slice(visibleCount);

        if (JSON.stringify(newVisibleLinks) !== JSON.stringify(visibleLinks)) {
            setVisibleLinks(newVisibleLinks);
            setHiddenLinks(newHiddenLinks);
        }
    };

    useEffect(() => {
        calculateLinks();
    }, [links]);

    useEffect(() => {
        const resizeObserver = new ResizeObserver(() => {
            try {
                calculateLinks();
            } catch (error) {
                console.error("Error en el Resize Observer:", error);
            }
        });

        if (navContainerRef.current) {
            resizeObserver.observe(navContainerRef.current);
        }

        return () => {
            if (navContainerRef.current) {
                resizeObserver.unobserve(navContainerRef.current);
            }
        };
    }, [navContainerRef]);

    return (
        <div ref={navContainerRef}>
            {visibleLinks.map(link => (
                <div key={link.id}>{link.name}</div>
            ))}
            <div ref={dummyContainerRef} style={{ display: 'none' }}>
                {links.map(link => (
                    <div key={link.id} style={{ display: 'inline-block' }}>{link.name}</div>
                ))}
            </div>
        </div>
    );
};

export default MyComponent;

Análisis del Código

  1. Referencias: Se utilizan las referencias (useRef) para acceder al contenedor de navegación y a un contenedor "dummy" que ayuda a medir el ancho de los elementos.

  2. Cálculo de Enlaces Visibles: La función calculateLinks calcula cuántos enlaces se pueden mostrar según el ancho del contenedor. Utiliza un bucle para sumar los anchos de los elementos hasta que supera el ancho del contenedor.

  3. Uso de Efectos:
    • Un useEffect se encarga de calcular los enlaces visibles cuando cambian los enlaces prop.
    • Otro useEffect crea un ResizeObserver para volver a calcular el ancho de los enlaces cuando se detecta un cambio de tamaño en el contenedor.

Conclusión

Implementar un ResizeObserver en React de manera efectiva puede mejorar significativamente la experiencia del usuario al mostrar contenido dinámico. Siguiendo esta guía, podrás manejar el tamaño de los enlaces adecuadamente, evitando llamadas innecesarias y optimizando el rendimiento de tu aplicación.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *