Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { useState, useRef, useEffect, RefObject, useCallback } from 'react'
- import { TScrollDirection } from './types'
- export const useScrollDirection = <T extends HTMLElement>(
- ref?: RefObject<T>,
- ) => {
- const [scrollDirection, setScrollDirection] = useState<TScrollDirection>('up')
- const threshold = useRef(0)
- const lastScrollY = useRef(0)
- const isTicking = useRef(false)
- const updateScrollDir = useCallback(() => {
- const scrollY = window.scrollY
- if (
- document.body.scrollHeight - document.documentElement.clientHeight <
- 100
- ) {
- setScrollDirection(undefined)
- return
- }
- if (Math.abs(scrollY - lastScrollY.current) < threshold.current) {
- isTicking.current = false
- return
- }
- if (
- scrollY < (ref?.current?.clientHeight ?? 200) * 2 &&
- scrollY > lastScrollY.current
- ) {
- lastScrollY.current = scrollY > 0 ? scrollY : 0
- isTicking.current = false
- return
- }
- if (scrollY > lastScrollY.current) {
- setScrollDirection('down')
- }
- if (scrollY < lastScrollY.current) {
- setScrollDirection('up')
- }
- lastScrollY.current = scrollY > 0 ? scrollY : 0
- isTicking.current = false
- }, [ref])
- useEffect(() => {
- threshold.current = 0
- lastScrollY.current = window.scrollY
- isTicking.current = false
- const onScroll = () => {
- if (!isTicking.current) {
- window.requestAnimationFrame(updateScrollDir)
- isTicking.current = true
- }
- }
- window.addEventListener('scroll', onScroll)
- return () => window.removeEventListener('scroll', onScroll)
- }, [scrollDirection, updateScrollDir])
- return { scrollDirection }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement