Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IntersectionObserverAPI Return to default state when none of the elements are visible

I'm using a React Hook to detect when an element is visible in the viewport. Until then, everything works fine but I need to 'reset' the state when everything is hidden (like reaching the footer or the header).

Here's my hook:

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

const useIntersect = (ref) => {
  const [isOnScreen, setIsOnScreen] = useState(false)
  const observerRef = useRef(null)

  useEffect(() => {
    observerRef.current = new IntersectionObserver(([entry]) => {
      setIsOnScreen(entry.isIntersecting)
    })
  }, [])

  useEffect(() => {
    observerRef.current.observe(ref.current)
    return () => observerRef.current.disconnect()
  }, [ref])

  return isOnScreen
}

export default useIntersect

And here's the state I'm updating:

  const elementRef = useRef(null)
  const[state, setState] = useState('nothing is visible')
  const onScreen = useIntersect(elementRef)

  useEffect(() => {
    return onScreen ? setState('an item is visible') : null
  })

  return (
    <Item ref={elementRef}>
      ...
    </Item>
  )

I need to be able to say setState('...') to something (let's say a string) when all the elements are off the viewport (when the condition onScreen is not met) but even when I reach the footer when nothing is visible, it keeps the last item in memory.

I've tried many things but I cannot figure a way out :(

Thanks for the help!

like image 318
user990463 Avatar asked Dec 20 '25 08:12

user990463


1 Answers

I believe your useIntersect hook should add a dependency on the ref.current instead of ref for the second useEffect

so

useEffect(() => {
  observerRef.current.observe(ref.current)
  return () => observerRef.current.disconnect()
}, [ref.current]);

and then when using it in the component do

useEffect(() => {
  return onScreen ? setState('an item is visible') : setState('nothing is visible');
}, [onScreen])

you should add a dependency on the onScreen so it only updates when the onScreen has changed, and lastly you should call setState for the scenario when the onScreen is false to the value you want.

like image 134
Gabriele Petrioli Avatar answered Dec 22 '25 22:12

Gabriele Petrioli



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!