Skip to content

Instantly share code, notes, and snippets.

@csandman
Last active October 7, 2020 18:37
Show Gist options
  • Save csandman/289787f26ae14566963ba611bf999c1f to your computer and use it in GitHub Desktop.
Save csandman/289787f26ae14566963ba611bf999c1f to your computer and use it in GitHub Desktop.
A react hook to add a scroll event listener with optional callbacks
// inspired by:
// https://gist.github.com/joshuacerbito/ea318a6a7ca4336e9fadb9ae5bbb87f4
import { useEffect, useState } from 'react';
const isValidFunction = (func) => {
return func && typeof func === 'function';
};
export default function useScroll({ onScroll, onScrollUp, onScrollDown }) {
const [scroll, setScroll] = useState(
typeof window === 'undefined' || !window.document
? { x: 0, y: 0, direction: '' }
: {
x: document.body.getBoundingClientRect().left,
y: -document.body.getBoundingClientRect().top,
direction: '',
}
);
useEffect(() => {
const handleScroll = () => {
setScroll((prevScroll) => {
const rect =
typeof window === 'undefined' || !window.document
? { left: 0, top: 0 }
: document.body.getBoundingClientRect();
const x = rect.left;
const y = -rect.top;
const direction = prevScroll.y > y ? 'up' : 'down';
const newScroll = { x, y, direction };
if (isValidFunction(onScroll)) {
onScroll(newScroll);
}
if (direction === 'up' && isValidFunction(onScrollUp)) {
onScrollUp(newScroll);
}
if (direction === 'down' && isValidFunction(onScrollDown)) {
onScrollDown(newScroll);
}
return newScroll;
});
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, [onScroll, onScrollDown, onScrollUp]);
return scroll;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment