Last active
January 20, 2020 18:17
-
-
Save jcarroll2007/30cede69f8fa1b2d86a23d84963212e3 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