-
-
Save washingtonsoares/7375ad7a6f7d72e795a60d7b9d06f3ca to your computer and use it in GitHub Desktop.
React Intersection Observer Hook: `useIsElementInView`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import useIsElementInView from './useIsElementInView' | |
export function Example() { | |
const { ref, isInView } = useIsElementInView() | |
return ( | |
<div ref={ref}> | |
{isInView ? 'It is in the view!' : 'Not in view (so you cant really even tell if it works I guess...)'} | |
</div> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useEffect, useRef, useCallback } from 'react' | |
/** | |
* The options to be passed to the intersection observer. Right now, | |
* there is a limited use-case. But this could certainly be improved in the future | |
* if necessary. | |
*/ | |
const observerOptions = { | |
root: null, | |
rootMargin: '0px', | |
threshold: 1.0 | |
} | |
export default function useIsElementInView(destroyAfterIntersect = false) { | |
const [destroyed, setDestroyed] = useState(false) | |
const [isInView, setIsInView] = useState(false) | |
const ref = useRef() | |
const observerCallback = useCallback( | |
entries => { | |
const entry = entries[0] | |
const isInFullView = entry.intersectionRatio === 1 | |
setIsInView(isInFullView) | |
if (isInFullView && destroyAfterIntersect) setDestroyed(true) | |
}, | |
[destroyAfterIntersect] | |
) | |
useEffect(() => { | |
const { current } = ref | |
// Refs are always null on the first render, so we need to account for that | |
if (!current || destroyed) return | |
const newObserver = new IntersectionObserver( | |
observerCallback, | |
observerOptions | |
) | |
newObserver.observe(current) | |
/** | |
* Cleanup | |
*/ | |
return () => newObserver.disconnect() | |
}, [ref, observerCallback, destroyed]) | |
return { | |
ref, | |
isInView | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment