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
handleScroll
function 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
).