Last active
July 9, 2024 15:25
-
-
Save HoraceShmorace/99480fa5cda245ceeedcf3c5e6218646 to your computer and use it in GitHub Desktop.
Custom hook for setting up an intersection observer on a DOM element to determine its visibility relative to a specified viewport or the default viewport. Implements the native `IntersectionObserver` JavaScript class.
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
/** | |
* Custom hook for setting up an intersection observer on a DOM element to determine its visibility relative to a specified viewport or the default viewport. Implements the native `IntersectionObserver` JavaScript class. | |
* | |
* @param {React.RefObject} ref - Required. The React ref object pointing | |
* @param {Object} options - The options for setting up the observer. | |
to the DOM element to observe. | |
* @param {Element|null} [options.root=null] - The element that is used as the viewport for checking visibility of the target. Defaults to the browser viewport if not specified. | |
* @param {string} [options.rootMargin="0px"] - The margin around the viewport or "root". Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). | |
* @param {number} [options.threshold=0.5] - A single number or array of numbers indicating at what percentage of the target's visibility the observer's callback should execute. Ranges from 0 to 1. | |
* @returns {boolean} True if a current interection is present for the element for which the the React ref was pssed. False otherwise. | |
* @example | |
* function MyComponent() { | |
* const ref = useRef(null); | |
* const { isIntersecting } = useIntersectionObserver({ ref }); | |
* | |
* return <div ref={ref}>isIntersecting: { isIntersecting? 'Y' : 'N' }!</div>; | |
* } | |
* | |
* @example https://codepen.io/HoraceShmorace/pen/GRLBBmM | |
* @see Complete example at https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver | |
*/ | |
const useIntersectionObserver = (ref, options = { | |
root: null, | |
rootMargin: "0px", | |
threshold: 0.5 | |
}) => { | |
if (!ref) throw "You must pass a reference {React.RefObject}."; | |
const [entry, setEntry] = useState(false); | |
const handleIntersection = (entries) => { | |
const [entry = {}] = entries; | |
setEntry(entry); | |
}; | |
useEffect(() => { | |
const rootElement = ref.current; | |
const observer = new IntersectionObserver(handleIntersection, options); | |
if (rootElement) { | |
observer.observe(rootElement); | |
} | |
return () => { | |
if (rootElement) observer.unobserve(rootElement); | |
observer.disconnect(); | |
}; | |
}, [ref.current]); | |
return entry; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment