Skip to content

Instantly share code, notes, and snippets.

@dance2die
Last active August 22, 2019 18:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dance2die/f26f7b64094d635ae8de5498c3ac4cb1 to your computer and use it in GitHub Desktop.
Save dance2die/f26f7b64094d635ae8de5498c3ac4cb1 to your computer and use it in GitHub Desktop.
function useObserveTopSentinels(
topSentinelRef,
// 1️⃣
{ events: { onStuck, onUnstuck, onChange } }
) {
// 2️⃣ Get the viewport root & the stick refs associated with the TOP sentinels
const { stickyRefs, containerRef } = useStickyState();
// 3️⃣ Start observing TOP sentinels
useEffect(() => {
if (!containerRef) return;
if (!containerRef.current) return;
const root = containerRef.current;
const options = { threshold: [0], root };
// 4️⃣ Create observers to monitor TOP sentinels
// Please refer to the Google doc on how this works.
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
const target = stickyRefs.get(entry.target);
const targetInfo = entry.boundingClientRect;
const rootBoundsInfo = entry.rootBounds;
let type = undefined;
// 5️⃣ the bottom of TOP sentinel moved up, so fire the "stuck" event.
if (targetInfo.bottom < rootBoundsInfo.top) {
type = "stuck";
onStuck(target);
}
// 6️⃣ the TOP sentinel is in the visible area. So fire "unstuck" event
if (
targetInfo.bottom >= rootBoundsInfo.top &&
targetInfo.bottom < rootBoundsInfo.bottom
) {
type = "unstuck";
onUnstuck(target);
}
// 7️⃣ Fire the event if either "un/stuck" even has been fired.
type && onChange({ type, target });
});
}, options);
// 8️⃣ Observe all TOP sentinels
const sentinel = topSentinelRef.current;
sentinel && observer.observe(sentinel);
return () => {
observer.unobserve(sentinel);
};
}, [topSentinelRef, onChange, onStuck, onUnstuck, stickyRefs, containerRef]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment