Advertisement
metalni

Untitled

Mar 19th, 2024
803
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { useState, useRef, useEffect, RefObject, useCallback } from 'react'
  2. import { TScrollDirection } from './types'
  3.  
  4. export const useScrollDirection = <T extends HTMLElement>(
  5.   ref?: RefObject<T>,
  6. ) => {
  7.   const [scrollDirection, setScrollDirection] = useState<TScrollDirection>('up')
  8.  
  9.   const threshold = useRef(0)
  10.   const lastScrollY = useRef(0)
  11.   const isTicking = useRef(false)
  12.  
  13.   const updateScrollDir = useCallback(() => {
  14.     const scrollY = window.scrollY
  15.  
  16.     if (
  17.       document.body.scrollHeight - document.documentElement.clientHeight <
  18.       100
  19.     ) {
  20.       setScrollDirection(undefined)
  21.       return
  22.     }
  23.  
  24.     if (Math.abs(scrollY - lastScrollY.current) < threshold.current) {
  25.       isTicking.current = false
  26.       return
  27.     }
  28.  
  29.     if (
  30.       scrollY < (ref?.current?.clientHeight ?? 200) * 2 &&
  31.       scrollY > lastScrollY.current
  32.     ) {
  33.       lastScrollY.current = scrollY > 0 ? scrollY : 0
  34.       isTicking.current = false
  35.  
  36.       return
  37.     }
  38.  
  39.     if (scrollY > lastScrollY.current) {
  40.       setScrollDirection('down')
  41.     }
  42.  
  43.     if (scrollY < lastScrollY.current) {
  44.       setScrollDirection('up')
  45.     }
  46.  
  47.     lastScrollY.current = scrollY > 0 ? scrollY : 0
  48.     isTicking.current = false
  49.   }, [ref])
  50.  
  51.   useEffect(() => {
  52.     threshold.current = 0
  53.     lastScrollY.current = window.scrollY
  54.     isTicking.current = false
  55.  
  56.     const onScroll = () => {
  57.       if (!isTicking.current) {
  58.         window.requestAnimationFrame(updateScrollDir)
  59.         isTicking.current = true
  60.       }
  61.     }
  62.  
  63.     window.addEventListener('scroll', onScroll)
  64.  
  65.     return () => window.removeEventListener('scroll', onScroll)
  66.   }, [scrollDirection, updateScrollDir])
  67.  
  68.   return { scrollDirection }
  69. }
  70.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement