From 978d931bd787b8dc99a98562ce7a5930d825d279 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Mon, 28 Apr 2025 19:38:54 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20create=20hook=20for=20rat?= =?UTF-8?q?e-limiting=20functions=20that=20could=20spam=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement custom hook to throttle JavaScript function calls and prevent interface performance degradation. --- src/frontend/src/hooks/useRateLimiter.ts | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/frontend/src/hooks/useRateLimiter.ts diff --git a/src/frontend/src/hooks/useRateLimiter.ts b/src/frontend/src/hooks/useRateLimiter.ts new file mode 100644 index 00000000..82ff8cda --- /dev/null +++ b/src/frontend/src/hooks/useRateLimiter.ts @@ -0,0 +1,37 @@ +import { useCallback, useRef } from 'react' + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type RateLimiterProps any> = { + callback: T + maxCalls: number + windowMs: number +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export default function useRateLimiter any>({ + callback, + maxCalls = 5, + windowMs = 1000, +}: RateLimiterProps) { + const callsCountRef = useRef(0) + const resetTimeoutRef = useRef(undefined) + + const rateLimitedFn = useCallback( + (...args: Parameters) => { + if (callsCountRef.current < maxCalls) { + callsCountRef.current += 1 + if (callsCountRef.current === 1) { + resetTimeoutRef.current = setTimeout(() => { + callsCountRef.current = 0 + resetTimeoutRef.current = undefined + }, windowMs) + } + return callback(...args) + } else { + return null + } + }, + [callback, maxCalls, windowMs] + ) + return rateLimitedFn +}