Skip to content

Instantly share code, notes, and snippets.

@jcarroll2007
Last active January 20, 2020 18:17
Show Gist options
  • Save jcarroll2007/30cede69f8fa1b2d86a23d84963212e3 to your computer and use it in GitHub Desktop.
Save jcarroll2007/30cede69f8fa1b2d86a23d84963212e3 to your computer and use it in GitHub Desktop.
React Intersection Observer Hook: `useIsElementInView`
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>
)
}
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