Skip to content

Instantly share code, notes, and snippets.

@gabehesse
Forked from joshuacerbito/useScroll.js
Last active July 1, 2019 15:11
Show Gist options
  • Save gabehesse/841eff6e55f436ca08c92434dd9bb38d to your computer and use it in GitHub Desktop.
Save gabehesse/841eff6e55f436ca08c92434dd9bb38d to your computer and use it in GitHub Desktop.
Custom React hook for listening to scroll events
/**
* useScroll React custom hook
* Usage:
* const { x, y, direction } = useScroll();
*/
import { useState, useEffect } from "react";
export default function useScroll() {
if(!process.browser) return {x: null, y: null, direction: null}
let rect = document.body.getBoundingClientRect()
const [scrollData, setScrollData] = useState({
lastScrollTop: 0,
bodyOffset: rect,
scrollX: rect.left,
scrollY: -rect.top,
scrollDirection: null
})
const debounce = (func, wait = 10, immediate = true) => {
let timeout
return (...args) => {
let context = this
let later = () => {
timeout = null
if (!immediate) func.apply(context, args)
}
let callNow = immediate && !timeout
clearTimeout(timeout)
timeout = setTimeout(later, wait)
if (callNow) func.apply(context, args)
}
}
const listener = () => {
rect = document.body.getBoundingClientRect()
const lastScrollTop = scrollData.lastScrollTop
setScrollData({
lastScrollTop: -rect.top,
bodyOffset: rect,
scrollX: rect.left,
scrollY: -rect.top,
scrollDirection: lastScrollTop > -rect.top ? 'up' : 'down'
})
}
const handler = debounce(listener, 50, true)
useEffect(() => {
window.addEventListener("scroll", handler);
return () => {
window.removeEventListener("scroll", handler);
}
});
return {
x: scrollData.scrollX,
y: scrollData.scrollY,
direction: scrollData.scrollDirection
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment