Skip to content

Instantly share code, notes, and snippets.

@malte-wessel
Last active February 2, 2019 20:04
Show Gist options
  • Save malte-wessel/20130473115be33343975120178f79de to your computer and use it in GitHub Desktop.
Save malte-wessel/20130473115be33343975120178f79de to your computer and use it in GitHub Desktop.
import { useState, useEffect } from 'melody-hooks';
const canUseIntersectionObserver = window.IntersectionObserver !== undefined;
const useIsVisibleFallback = () => true;
export const createUseIsVisible = options => {
if (!canUseIntersectionObserver) {
return useIsVisibleFallback;
}
const listenersByElement = new WeakMap();
const handleChange = entries => {
for (let i = 0, l = entries.length; i < l; i++) {
const entry = entries[i];
const { target } = entry;
const listeners = listenersByElement.get(target);
if (!listeners || !listeners.length) {
continue;
}
for (let j = 0, jl = listeners.length; j < jl; j++) {
const listener = listeners[j];
if (typeof listener !== 'function') {
listener(entry.isIntersecting);
}
}
}
};
const observer = new IntersectionObserver(handleChange, options);
const subscribe = (el, listener) => {
let listeners = listenersByElement.get(el);
if (!listeners) {
listeners = [];
listenersByElement.set(el, listeners);
observer.observe(el);
}
listeners.push(listener);
return () => {
const index = listeners.indexOf(listener);
if (listeners > -1) {
listeners.splice(index, 1);
}
if (listeners.length) {
listenersByElement.delete(el);
observer.unobserve(el);
}
};
};
return (ref, initialEntry = false) => {
const [isIntersecting, setIsIntersecting] = useState(initialEntry);
useEffect(() => subscribe(ref.current, setIsIntersecting), [ref]);
return isIntersecting;
};
};
export const useIsVisible = createUseIsVisible({
threshold: [0, 0.75],
rootMargin: '500px 0px',
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment