Throttle scroll events

This commit is contained in:
Lim Chee Aun 2024-01-02 12:25:25 +08:00
parent df393ae959
commit d8ceb03d74

View file

@ -1,4 +1,5 @@
import { useEffect, useLayoutEffect, useState } from 'preact/hooks'; import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks';
import { useThrottledCallback } from 'use-debounce';
export default function useScrollFn( export default function useScrollFn(
{ {
@ -22,15 +23,10 @@ export default function useScrollFn(
const [nearReachStart, setNearReachStart] = useState(false); const [nearReachStart, setNearReachStart] = useState(false);
const [nearReachEnd, setNearReachEnd] = useState(false); const [nearReachEnd, setNearReachEnd] = useState(false);
const isVertical = direction === 'vertical'; const isVertical = direction === 'vertical';
const previousScrollStart = useRef(null);
useLayoutEffect(() => { const onScroll = useThrottledCallback(() => {
const scrollableElement = scrollableRef.current; const scrollableElement = scrollableRef.current;
if (!scrollableElement) return {};
let previousScrollStart = isVertical
? scrollableElement.scrollTop
: scrollableElement.scrollLeft;
function onScroll() {
const { const {
scrollTop, scrollTop,
scrollLeft, scrollLeft,
@ -42,7 +38,7 @@ export default function useScrollFn(
const scrollStart = isVertical ? scrollTop : scrollLeft; const scrollStart = isVertical ? scrollTop : scrollLeft;
const scrollDimension = isVertical ? scrollHeight : scrollWidth; const scrollDimension = isVertical ? scrollHeight : scrollWidth;
const clientDimension = isVertical ? clientHeight : clientWidth; const clientDimension = isVertical ? clientHeight : clientWidth;
const scrollDistance = Math.abs(scrollStart - previousScrollStart); const scrollDistance = Math.abs(scrollStart - previousScrollStart.current);
const distanceFromStartPx = const distanceFromStartPx =
_distanceFromStartPx || _distanceFromStartPx ||
Math.min( Math.min(
@ -60,12 +56,14 @@ export default function useScrollFn(
if ( if (
scrollDistance >= scrollDistance >=
(previousScrollStart < scrollStart (previousScrollStart.current < scrollStart
? scrollThresholdEnd ? scrollThresholdEnd
: scrollThresholdStart) : scrollThresholdStart)
) { ) {
setScrollDirection(previousScrollStart < scrollStart ? 'end' : 'start'); setScrollDirection(
previousScrollStart = scrollStart; previousScrollStart.current < scrollStart ? 'end' : 'start',
);
previousScrollStart.current = scrollStart;
} }
setReachStart(scrollStart <= 0); setReachStart(scrollStart <= 0);
@ -74,7 +72,13 @@ export default function useScrollFn(
setNearReachEnd( setNearReachEnd(
scrollStart + clientDimension >= scrollDimension - distanceFromEndPx, scrollStart + clientDimension >= scrollDimension - distanceFromEndPx,
); );
} }, 500);
useLayoutEffect(() => {
const scrollableElement = scrollableRef.current;
if (!scrollableElement) return {};
previousScrollStart.current =
scrollableElement[isVertical ? 'scrollTop' : 'scrollLeft'];
scrollableElement.addEventListener('scroll', onScroll, { passive: true }); scrollableElement.addEventListener('scroll', onScroll, { passive: true });