2022-02-11 17:24:33 +00:00
|
|
|
import { useRef, useEffect, useState, useCallback } from 'react'
|
|
|
|
|
|
|
|
|
|
type ScrollOffset = {
|
|
|
|
|
x: number
|
|
|
|
|
y: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type ScrollOffsetChangeset = {
|
|
|
|
|
current: ScrollOffset
|
|
|
|
|
previous: ScrollOffset
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Effect = (offset: ScrollOffsetChangeset) => void
|
|
|
|
|
|
|
|
|
|
export function useScrollWatcher(
|
|
|
|
|
effect: Effect,
|
|
|
|
|
delay: number
|
|
|
|
|
): void {
|
|
|
|
|
const throttleTimeout = useRef<NodeJS.Timeout | undefined>(undefined)
|
|
|
|
|
const [currentOffset, setCurrentOffset] = useState<ScrollOffset>({
|
|
|
|
|
x: 0,
|
|
|
|
|
y: 0,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const callback = () => {
|
|
|
|
|
const newOffset = {
|
2022-06-17 22:59:41 +00:00
|
|
|
x: window.document.documentElement.scrollLeft ?? window?.scrollX ?? 0,
|
|
|
|
|
y: window.document.documentElement.scrollTop ?? window?.scrollY ?? 0,
|
2022-02-11 17:24:33 +00:00
|
|
|
}
|
|
|
|
|
effect({ current: newOffset, previous: currentOffset })
|
|
|
|
|
setCurrentOffset(newOffset)
|
|
|
|
|
throttleTimeout.current = undefined
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleScroll = () => {
|
|
|
|
|
if (typeof throttleTimeout.current === 'undefined') {
|
|
|
|
|
throttleTimeout.current = setTimeout(callback, delay)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-17 22:59:41 +00:00
|
|
|
window.addEventListener('scroll', handleScroll)
|
2022-02-11 17:24:33 +00:00
|
|
|
return () =>
|
2022-06-17 22:59:41 +00:00
|
|
|
window.removeEventListener('scroll', handleScroll)
|
|
|
|
|
}, [currentOffset, delay, effect])
|
2022-02-11 17:24:33 +00:00
|
|
|
}
|