mirror of
https://github.com/zhigang1992/react.git
synced 2026-01-29 17:18:13 +08:00
feat: add body scroll hooks
This commit is contained in:
56
components/utils/use-body-scroll.ts
Normal file
56
components/utils/use-body-scroll.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Dispatch, MutableRefObject, SetStateAction, useEffect, useRef, useState } from 'react'
|
||||
|
||||
export type ElementStackItem = {
|
||||
last: string
|
||||
}
|
||||
|
||||
const elementStack = new Map<HTMLElement, ElementStackItem>()
|
||||
|
||||
const isIos = () => {
|
||||
if (typeof window === 'undefined' || !window.navigator) return false
|
||||
return /iP(ad|hone|od)/.test(window.navigator.platform)
|
||||
}
|
||||
|
||||
const touchHandler = (event: TouchEvent): boolean => {
|
||||
if (event.touches.length > 1) return true
|
||||
event.preventDefault()
|
||||
return false
|
||||
}
|
||||
|
||||
const useBodyScroll = (
|
||||
elementRef?: MutableRefObject<HTMLElement>
|
||||
): [boolean, Dispatch<SetStateAction<boolean>>] => {
|
||||
if (typeof document === 'undefined') return [false, (t: boolean) => t]
|
||||
const elRef = elementRef || useRef<HTMLElement>(document.body)
|
||||
const [hidden, setHidden] = useState<boolean>(false)
|
||||
|
||||
useEffect(() => {
|
||||
const lastOverflow = elRef.current.style.overflow
|
||||
if (hidden) {
|
||||
if (elementStack.has(elRef.current)) return
|
||||
if (!isIos()) {
|
||||
elRef.current.style.overflow = 'hidden'
|
||||
} else {
|
||||
document.addEventListener('touchmove', touchHandler, { passive: false })
|
||||
}
|
||||
elementStack.set(elRef.current, {
|
||||
last: lastOverflow,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// reset element overflow
|
||||
if (!elementStack.has(elRef.current)) return
|
||||
if (!isIos()) {
|
||||
const store = elementStack.get(elRef.current) || { last: 'auto' }
|
||||
elRef.current.style.overflow = store.last
|
||||
} else {
|
||||
document.removeEventListener('touchmove', touchHandler)
|
||||
}
|
||||
elementStack.delete(elRef.current)
|
||||
}, [hidden, elRef.current])
|
||||
|
||||
return [hidden, setHidden]
|
||||
}
|
||||
|
||||
export default useBodyScroll
|
||||
Reference in New Issue
Block a user