Skip to content

Commit

Permalink
refactor: previous logic fix and timeoutId refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Xaroz committed Oct 21, 2024
1 parent 9eb22da commit 58b67b4
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/components/nav/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function Header({ pathName }: { pathName: string }) {
>
<div className="flex items-center justify-between">
<Link href="/" className="flex items-center">
{/* We are adding a minimal rotation here to trick the browser to go into hardware acceleration mode
{/* Add a minimal rotation here to trick the browser to go into hardware acceleration mode
this will make the animation a little smoother, specially for Firefox*/}
<div
className={`flex items-center ${
Expand Down
3 changes: 0 additions & 3 deletions src/utils/browser.ts

This file was deleted.

68 changes: 31 additions & 37 deletions src/utils/useScrollListener.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,44 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';

export function useScrollThresholdListener(threshold: number, debounceTime = 200) {
export function useScrollThresholdListener(threshold: number, debounce = 300) {
const [isAboveThreshold, setIsAbove] = useState(false);
const [isDebouncing, setIsDebouncing] = useState(false);

const timeoutId = useRef<null | NodeJS.Timeout>(null);

const handleScroll = useCallback(() => {
if (isDebouncing) return; // Skip handling scroll when disabled

if (window.scrollY > threshold && !isAboveThreshold) {
setIsAbove(true);
setIsDebouncing(true);
} else if (window.scrollY <= threshold && isAboveThreshold) {
setIsAbove(false);
setIsDebouncing(true);
}
}, [threshold, isAboveThreshold, isDebouncing]);

const debouncedHandleScroll = debounce(handleScroll, 20);
const timeoutId = useRef<NodeJS.Timeout | null>(null);

useEffect(() => {
if (isDebouncing && !timeoutId.current) {
timeoutId.current = setTimeout(() => {
setIsDebouncing(false);
timeoutId.current = null;
}, debounceTime);
}

window.addEventListener('scroll', debouncedHandleScroll, { passive: true });
const listener = () => {
const handleScroll = () => {
if (isDebouncing) return;

if (window.scrollY > threshold && !isAboveThreshold) {
setIsAbove(true);
setIsDebouncing(true);
} else if (window.scrollY <= threshold && isAboveThreshold) {
setIsAbove(false);
setIsDebouncing(true);
}
};

if (isDebouncing) {
if (!timeoutId.current) {
timeoutId.current = setTimeout(() => {
setIsDebouncing(false);
timeoutId.current = null;
handleScroll();
}, debounce);
}
} else {
handleScroll();
}
};

window.addEventListener('scroll', listener, { passive: true });
return () => {
window.removeEventListener('scroll', debouncedHandleScroll);
window.removeEventListener('scroll', listener);
if (timeoutId.current) clearTimeout(timeoutId.current);
};
}, [debouncedHandleScroll, isDebouncing, debounceTime]);
}, [threshold, debounce, isAboveThreshold, isDebouncing]);

return isAboveThreshold;
}

function debounce(fn: () => void, delay: number) {
let timeoutId: number;
return function () {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = window.setTimeout(fn, delay);
};
}

0 comments on commit 58b67b4

Please sign in to comment.