useScrollPosition
Prompt
Create a custom React hook called useScrollPosition that tracks the window's scroll position on both the X and Y axes.
Requirements
- The hook should return an object with the following properties:
x: The current horizontal scroll position (scrollX)y: The current vertical scroll position (scrollY)
- The hook should update the scroll position whenever the user scrolls
Example
function ScrollTracker() {
const { x, y } = useScrollPosition();
return (
<div>
{x} {y}
</div>
);
}Playground
Start by creating a state variable with useState to store the scroll position as an object with x and y properties.
Use the useEffect hook to add an event listener for the 'scroll' event on the window object.
Remember to remove the event listener in the cleanup function returned by useEffect to prevent memory leaks.
Solution
Explanation
Our useScrollPosition hook is quite straightforward! Let's see how it works:
First, we create a state variable to keep track of both X and Y scroll positions:
const [scrollPosition, setScrollPosition] = useState({
x: 0,
y: 0,
});Next, we use useEffect to set up an event listener for scrolling:
useEffect(() => {
function handleScroll() {
setScrollPosition({
x: Math.round(window.scrollX),
y: Math.round(window.scrollY),
});
}
window.addEventListener('scroll', handleScroll);
// Clean up the event listener when the component unmounts
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);This useEffect does a few key things:
- Creates a
handleScrollfunction that updates our state with the current scroll position - Adds it as an event listener to the window's 'scroll' event
- Returns a cleanup function that removes the event listener when the component unmounts
We use an empty dependency array ([]) to ensure our effect only runs once when the component mounts.
Finally, we return the scroll position object so components using our hook can access it:
return scrollPosition;That's it! This hook is a great example of how React's built-in hooks can be combined to create reusable pieces of functionality.
Why do we use Math.round() for the scroll values? Browsers return fractional pixel values for scroll positions (like 100.33333px).