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
-
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. -
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. - Uso de Efectos:
- Un
useEffect
se encarga de calcular los enlaces visibles cuando cambian los enlaces prop. - Otro
useEffect
crea unResizeObserver
para volver a calcular el ancho de los enlaces cuando se detecta un cambio de tamaño en el contenedor.
- Un
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.