Custom React Hook To Determine Scroll Direction
I wanted the navigation bar of my portfolio website to disappear upon scrolling down, and reappear upon scrolling up.
Initally the navigation bar is displayed
Upon scrolling down, the navgiation bar disappears
Upon scrolling back up, navigation bar reappears.
To achieve the above functionality I used React Hooks to write a customized hook that would determine the users scrolling direction.
The navigation bar component used the returned direction value from the hook to apply the appropriate css style to itself.
If the user was at the top of the page, the navigation bar was displayed at the top with no special css styling applied to it.
The Logic Behind My useScrollDirection Hook
To determine the amount scrolled by the user I used window.scrollY
. The scrollY property on the browser window object returned the number of pixels the document was scrolled vertically.
Initially window.scrollY
is 0 and the more the user scrolls down the larger it gets.
Within the custom hook I had two states:
- The scrolled direction, initially null
- The previous scrolled amount from the top of the page, initially 0
const [scrollDirection, setScrollDirection] = useState(null)
const [prevOffset, setPrevOffset] = useState(0)
I also subscribed an event listener to the window scrolling event. I set up the subscription with the help of the effect hook.
useEffect(() => {
window.addEventListener("scroll", toggleScrollDirection)
return () => {
window.removeEventListener("scroll", toggleScrollDirection)
}
})
Every time the user scrolled, toggleScrollDirection
was invoked.
Inside the function, the amount scrolled by the user was captured by a variable
let scrollY = window.scrollY
And then for every time scrolling happened the following conditions were checked in order to set the appropriate scrolling direction state value.
if (scrollY === 0) {
setScrollDirection(null)
}
if (scrollY > prevOffset){
setScrollDirection("down")
} else if (scrollY < prevOffset) {
setScrollDirection("up")
}
setPrevOffset(scrollY);
If the user was at the top of the page, scrollY would be zero, and so we set the set the scrolling direction as null.
If the user was scrolling down, then the scrollY value would be greater than the last scrollY value stored in the prevOffset
state.
The exact opposite was true when the user scrolled up. In both cases the scrollDirection
state would be set appropriately.
Finally, the prevOffset
would be set as this last scrollY value, to be referenced the next time the user scrolled.
The entire Hook Code was
const useScrollDirection = () => {
const [scrollDirection, setScrollDirection] = useState(null)
const [prevOffset, setPrevOffset] = useState(0)
const toggleScroll = () => {
let scrollY = window.scrollY
if (scrollY === 0) {
setScrollDirection(null)
}
if (scrollY > prevOffset) {
setScrollDirection("down")
} else if (scrollY < prevOffset) {
setScrollDirection("up")
}
setPrevOffset(scrollY)
}
useEffect(() => {
window.addEventListener("scroll", toggleScroll)
return () => {
window.removeEventListener("scroll", toggleScroll)
}
})
return scrollDirection
}
The Navigation Bar Component Utilized Return Value Of The Hook
Inside the Navbar component we captured the scroll direction value returned from the useScrollDirection hook.
const scrollDirection = useScrollDirection()
Then according to scrollDirection
, we would apply appropriate css styles to the navigation bar.
The styling of the navigation bar can be done in many different ways so I leave that out of this article.
This is my very first article published on Medium. Forgive me for the subpar writing. I hope to improve as I write more!