story-research-zapwall/hooks/useInfiniteScroll.ts
2026-01-15 12:12:05 +01:00

58 lines
1.2 KiB
TypeScript

import { useEffect, useRef, useState } from 'react'
interface UseInfiniteScrollOptions {
hasMore: boolean
loading: boolean
onLoadMore: () => void
threshold?: number
}
export function useInfiniteScroll({
hasMore,
loading,
onLoadMore,
threshold = 200,
}: UseInfiniteScrollOptions): React.RefObject<HTMLDivElement | null> {
const observerRef = useRef<HTMLDivElement>(null)
const [isIntersecting, setIsIntersecting] = useState(false)
useEffect(() => {
if (!hasMore || loading) {
return
}
const observer = new IntersectionObserver(
(entries) => {
const entry = entries[0]
if (entry?.isIntersecting) {
setIsIntersecting(true)
} else {
setIsIntersecting(false)
}
},
{
rootMargin: `${threshold}px`,
}
)
const currentRef = observerRef.current
if (currentRef) {
observer.observe(currentRef)
}
return () => {
if (currentRef) {
observer.unobserve(currentRef)
}
}
}, [hasMore, loading, threshold])
useEffect(() => {
if (isIntersecting && hasMore && !loading) {
onLoadMore()
}
}, [isIntersecting, hasMore, loading, onLoadMore])
return observerRef
}