-
Notifications
You must be signed in to change notification settings - Fork 48
/
useWindowScroller.js
45 lines (40 loc) 路 1.45 KB
/
useWindowScroller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import {useState, useEffect, useRef} from 'react'
import emptyArr from 'empty/array'
import emptyObj from 'empty/object'
import useLayoutEffect from '@react-hook/passive-layout-effect'
import useWindowScroll from '@react-hook/window-scroll'
import useWindowSize from '@react-hook/window-size'
const defaultSizeOpt = {wait: 120}
const defaultScrollFps = 8
export default (initialWidth, initialHeight, opt = emptyObj) => {
const fps = opt.scroll?.fps || defaultScrollFps
const scrollY = useWindowScroll(fps)
const [width, height] = useWindowSize(
initialWidth,
initialHeight,
opt.size || defaultSizeOpt
)
const [isScrolling, setIsScrolling] = useState(false)
const isScrollingTimeout = useRef(null)
useLayoutEffect(() => {
if (isScrollingTimeout.current !== null) {
clearTimeout(isScrollingTimeout.current)
isScrollingTimeout.current = null
}
setIsScrolling(true)
isScrollingTimeout.current = setTimeout(() => {
// This is here to prevent premature bail outs while maintaining high resolution
// unsets. Without it there will always bee a lot of unnecessary DOM writes to style.
setIsScrolling(false)
isScrollingTimeout.current = null
}, 1000 / 6)
}, [scrollY])
// cleans up isScrollingTimeout on unmount
useEffect(
() => () =>
isScrollingTimeout.current !== null &&
clearTimeout(isScrollingTimeout.current),
emptyArr
)
return {width, height, scrollY, isScrolling}
}