Goal
We will create a React custom hook which will tell us whether we have scrolled beyond a certain vertical position or not.
This specific implementation returns a boolean value only: "whether our scrolling has exceeded a given y-value or not", because we want the hook to expose no more than the needed information.
I am currently using this to make my "page fixed header" taller to display more info, when the user scrolls past the first part of the page and this part disappears from sight.
Why this hook?
When we scroll from A to B, the currently used scroll detections (onscroll event) normally trigger multiple times, which can slow down the page.
Note
What is a "React custom hook"? One definition (or my definition) is:
-- if a function is named "use.." and calls at least one other React hook,
then it's a "React custom hook".
Document scrollend event is newly available on Firefox and Chrome. caniuse
First we will create a file "hooks/useScrollExceeds.ts"
import { useEffect } from "react";
const useScrollExceeds = (
exceedY: number,
setScrollExceeds: (exceeds: boolean) => void
) => {
useEffect(() => {
const callOnScrollEnd = (): void => {
setScrollExceeds(window.pageYOffset >= exceedY);
};
document.addEventListener("scrollend", callOnScrollEnd);
return () => {
document.removeEventListener("scrollend", callOnScrollEnd);
};
}, []); // eslint-disable-line react-hooks/exhaustive-deps
};
export default useScrollExceeds;
Then in our own component file, for example Page.tsx
import { useScrollExceeds } from "../hooks";
...
const Page = () => {
const [scrollExceeds, setScrollExceeds] = useState(false);
useScrollExceeds(123, setScrollExceeds); // 123: y-value we want to check for
const someFunction = () => {
if (scrollExceeds) {
// do something if we've scrolled more than 123 pixels vertically
}
}
// Or pass the information to some other component
return (
...
<Header scrollExceeds={scrollExceeds}>
...
Top comments (0)