Skip to content

Commit

Permalink
fix: optimize useScrollPosition with useCallback and useRef
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaic4o committed May 22, 2024
1 parent 06ecd21 commit c423a9d
Showing 1 changed file with 16 additions and 9 deletions.
25 changes: 16 additions & 9 deletions packages/hooks/use-scroll-position/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {useRef, useEffect} from "react";
import {useRef, useEffect, useCallback} from "react";

const isBrowser = typeof window !== "undefined";

export type ScrollValue = {x: any; y: any};
export type ScrollValue = {x: number; y: number};

function getScrollPosition(element: HTMLElement | undefined | null): ScrollValue {
if (!isBrowser) return {x: 0, y: 0};
Expand Down Expand Up @@ -41,26 +41,28 @@ export const useScrollPosition = (props: UseScrollPositionOptions): ScrollValue
isEnabled ? getScrollPosition(elementRef?.current) : {x: 0, y: 0},
);

let throttleTimeout: ReturnType<typeof setTimeout> | null = null;
const throttleTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);

const handler = () => {
const handler = useCallback(() => {
const currPos = getScrollPosition(elementRef?.current);

if (typeof callback === "function") {
callback({prevPos: position.current, currPos});
}

position.current = currPos;
throttleTimeout = null;
};
throttleTimeout.current = null;
}, [callback, elementRef]);

useEffect(() => {
if (!isEnabled) return;

const handleScroll = () => {
if (delay) {
if (throttleTimeout === null) {
throttleTimeout = setTimeout(handler, delay);
if (throttleTimeout.current === null) {
throttleTimeout.current = setTimeout(() => {
handler();
}, delay);
}
} else {
handler();
Expand All @@ -71,7 +73,12 @@ export const useScrollPosition = (props: UseScrollPositionOptions): ScrollValue

target.addEventListener("scroll", handleScroll);

return () => target.removeEventListener("scroll", handleScroll);
return () => {
target.removeEventListener("scroll", handleScroll);
if (throttleTimeout.current) {
clearTimeout(throttleTimeout.current);
}
};
}, [elementRef?.current, delay, isEnabled]);

return position.current;
Expand Down

0 comments on commit c423a9d

Please sign in to comment.