Custom React Hook To Determine Scroll Direction

Sanjar Kairosh
September 10th, 20203 min read
Photo by Lynda Hinton on Unsplash

I wanted the navigation bar of my portfolio website to disappear upon scrolling down, and reappear upon scrolling up.

wnvbar.png

Initally the navigation bar is displayed

wonvbr.png

Upon scrolling down, the navgiation bar disappears

wnvbr2.png

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:

  1. The scrolled direction, initially null
  2. 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!

Blogs

copyright ©2021 all rights reserved, Sanjar Kairosh
illusrations by icons8