es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

IntersectionObserver no se actualiza en React.

El siguiente código activará un cambio de estado tan pronto como el elemento entre o salga de la ventana de visualización al desplazarse.

const dialog = useRef(),
[visible, set] = useState(false)

useEffect(() => {
        const observer = new IntersectionObserver((e) => {
            set(e[0].isIntersecting ? true : false)
        }, {root: null, rootMargin: '0px', threshold: 0})
        observer.observe(dialog.current)
        return () => observer.disconnect()
    }, [dialog.current])

return <div ref="{dialog}">mi diálogo</div>

pero si intento algo como esto

const observer = new IntersectionObserver((e) => {
            set(e[0].boundingClientRect.y <= 0 ? true : false)
        }, {root: null, rootMargin: '0px', threshold: 0})

el estado solo se actualiza si se activa una nueva representación, mientras que quiero que se active cuando desplazo la ventana de visualización, basado en el valor boundingClientRect.y del elemento observado.
La única forma que encontré para que esto funcione es utilizando el evento window.onscroll dentro de useEffect y colocando el observador dentro de él, pero no me parece muy adecuado. ¿Existe una forma diferente (y mejor) que utilizar window.onscroll?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Sí, hay una forma mejor de lograr el comportamiento deseado sin usar window.onscroll. En lugar de utilizar el método IntersectionObserver, se puede utilizar el gancho useLayoutEffect para calcular el rectángulo delimitador del elemento observado en cada renderizado. Aquí tienes un ejemplo de cómo se puede hacer:

    const dialog = useRef(),
    [visible, set] = useState(false)
    
    useLayoutEffect(() => {
      const handleScroll = () => {
        const boundingRect = dialog.current.getBoundingClientRect()
        set(boundingRect.y <= window.innerHeight && boundingRect.bottom >= 0)
      }
    
      window.addEventListener('scroll', handleScroll)
    
      return () => window.removeEventListener('scroll', handleScroll)
    }, [])
    
    return <div ref="{dialog}">mi diálogo</div>
    

    Aquí, estamos utilizando el gancho useLayoutEffect para agregar y quitar un evento al escuchar en el objeto window cada vez que se monta o desmonta el componente. La función handleScroll se llama en cada evento de desplazamiento, capturando el rectángulo delimitador del elemento observado y utilizándolo para calcular si está en vista o no. Luego, se llama a la función set para actualizar el estado de la variable visible en consecuencia. Al usar useLayoutEffect en lugar de useEffect, garantizamos que el comportamiento de desplazamiento se actualice inmediatamente después de cambiar el estado.

Comments are closed.