react-hook-inview
Version:
React Hook for detecting when an element is in the viewport
44 lines (43 loc) • 1.66 kB
JavaScript
import { useEffect, useState, useCallback, } from "react";
import useObserver from "./useObserver";
/**
* useInView
* @param options IntersectionObserverInit
* @param externalState React.ComponentState[]
*/
const useInView = ({ root, rootMargin, threshold, unobserveOnEnter, target, onEnter, onLeave, defaultInView } = {}, externalState = []) => {
const [state, setState] = useState({
inView: defaultInView || false,
entry: null,
observer: null,
});
const callback = useCallback(([entry], observer) => {
const inThreshold = observer.thresholds.some((t) => entry.intersectionRatio >= t);
const inView = inThreshold && entry.isIntersecting;
setState({
inView,
entry,
observer,
});
// unobserveOnEnter
if (inView && unobserveOnEnter) {
observer.unobserve(entry.target);
observer.disconnect();
}
// Legacy callbacks
if (inView) {
onEnter === null || onEnter === void 0 ? void 0 : onEnter(entry, observer);
}
else {
onLeave === null || onLeave === void 0 ? void 0 : onLeave(entry, observer);
}
}, [onEnter, onLeave, unobserveOnEnter]);
const setTarget = useObserver(callback, { root, rootMargin, threshold }, [unobserveOnEnter, ...externalState]);
// Legacy 'target' option
useEffect(() => {
if (target === null || target === void 0 ? void 0 : target.current)
setTarget(target.current);
}, [target, setTarget]);
return [setTarget, state.inView, state.entry, state.observer];
};
export default useInView;