Skip to content

Instantly share code, notes, and snippets.

@viclafouch
Last active June 17, 2020 19:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save viclafouch/259cbc31be65895833072a43d5f44d34 to your computer and use it in GitHub Desktop.
Save viclafouch/259cbc31be65895833072a43d5f44d34 to your computer and use it in GitHub Desktop.
A custom React Hook to handle the scroll of a DOM element.
// hooks/use-scroll.js
import { useEffect, useRef, useCallback, useState } from 'react'
function useScroll({ threshold = 450, isWindow = false, smooth = true } = {}) {
const [isAtBottom, setIsAtBottom] = useState(false)
const ref = useRef(isWindow ? window : null)
const goTop = useCallback(() => {
const element = ref.current
element.scrollTo({
top: 0,
behavior: smooth ? 'smooth' : 'auto'
})
}, [smooth])
const goBottom = useCallback(() => {
const element = ref.current instanceof Window ? document.documentElement : ref.current
ref.current.scrollTo({
top: element.scrollHeight,
behavior: smooth ? 'smooth' : 'auto'
})
}, [smooth])
const handleScroll = useCallback(() => {
if (ref.current) {
let isAtBottom
if (ref.current instanceof Window) {
const currentScrollTop = window.innerHeight + window.scrollY
isAtBottom = currentScrollTop >= document.documentElement.offsetHeight - threshold
} else {
const currentScrollTop = ref.current.offsetHeight + ref.current.scrollTop
isAtBottom = currentScrollTop >= ref.current.scrollHeight - threshold
}
setIsAtBottom(isAtBottom)
}
}, [threshold])
useEffect(() => {
if (isWindow) {
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}
}, [isWindow, handleScroll])
return { isAtBottom, handleScroll, goTop, goBottom, ref }
}
export default useScroll
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment