Skip to content

Instantly share code, notes, and snippets.

@reecelucas
Last active September 8, 2021 20:07
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save reecelucas/cd110ece696cca8468db895281fa28cb to your computer and use it in GitHub Desktop.
Save reecelucas/cd110ece696cca8468db895281fa28cb to your computer and use it in GitHub Desktop.
React hook to detect scroll direction, based on the API of https://github.com/dollarshaveclub/scrolldir
const SCROLL_UP = "up";
const SCROLL_DOWN = "down";
const useScrollDirection = ({
initialDirection,
thresholdPixels,
off
} = {}) => {
const [scrollDir, setScrollDir] = useState(initialDirection);
useEffect(() => {
const threshold = thresholdPixels || 0;
let lastScrollY = window.pageYOffset;
let ticking = false;
const updateScrollDir = () => {
const scrollY = window.pageYOffset;
if (Math.abs(scrollY - lastScrollY) < threshold) {
// We haven't exceeded the threshold
ticking = false;
return;
}
setScrollDir(scrollY > lastScrollY ? SCROLL_DOWN : SCROLL_UP);
lastScrollY = scrollY > 0 ? scrollY : 0;
ticking = false;
};
const onScroll = () => {
if (!ticking) {
window.requestAnimationFrame(updateScrollDir);
ticking = true;
}
};
/**
* Bind the scroll handler if `off` is set to false.
* If `off` is set to true reset the scroll direction.
*/
!off
? window.addEventListener("scroll", onScroll)
: setScrollDir(initialDirection);
return () => window.removeEventListener("scroll", onScroll);
}, [initialDirection, thresholdPixels, off]);
return scrollDir;
};
@n1xn
Copy link

n1xn commented Jul 16, 2019

Thank you very much!

@dillonstreator
Copy link

I'm noticing something a bit weird.

I use this hook in a Gatsbyjs project and when I do a standard refresh (ctrl+r), the scroll direction is determined as up but when I do a hard refresh (ctrl+shift+r), the scroll direction is determined as down.

I use Brave browser so chromium engine. I would expect same output whether regular refresh or hard refresh before any user input scrolling has occurred.
Any thoughts on why this might be happening or if anyone else has noticed this?

Either way, appreciate the gist!

@mokaymokay
Copy link

I'm noticing something a bit weird.

I use this hook in a Gatsbyjs project and when I do a standard refresh (ctrl+r), the scroll direction is determined as up but when I do a hard refresh (ctrl+shift+r), the scroll direction is determined as down.

I use Brave browser so chromium engine. I would expect same output whether regular refresh or hard refresh before any user input scrolling has occurred.
Any thoughts on why this might be happening or if anyone else has noticed this?

Either way, appreciate the gist!

I'm using this hook for a Next.js project with server side rendering, similar to Gatsby. The issue is probably due to the discrepancy between SSR and CSR. Try adding a default for SSR when there is no window available, i.e.:

 if (!process.browser) return SCROLL_UP; 

@shobhit-jain
Copy link

Try this -

Install this package from npm - https://www.npmjs.com/package/react-use-scroll-direction

Then Detect Scroll Direction : - )

import React from 'react'
import { useScrollDirection } from 'react-use-scroll-direction'

export const Window_Scroll_Direction = () => {
  const [direction, setDirection] = React.useState(String)
  const { isScrollingUp, isScrollingDown } = useScrollDirection()

  React.useEffect(() => {
    isScrollingDown && setDirection('down')
    isScrollingUp && setDirection('up')
  }, [isScrollingDown, isScrollingUp])

  return (
    <>
      <div className="fixed top-0 bg-white">
        {direction === 'down' ? 'Scrolling down' : 'scrolling up'}
      </div>
    </>
  )
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment