From b6cc2008a239aafb677f04bccdde6e861128318a Mon Sep 17 00:00:00 2001 From: Sahaj Jain Date: Thu, 17 Apr 2025 16:34:28 +0530 Subject: [PATCH] fix: debounce func --- components/editor/color-picker.tsx | 19 +++++++++++-------- utils/debounce.ts | 15 ++++++++++++--- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/components/editor/color-picker.tsx b/components/editor/color-picker.tsx index c721c25f..a64875bc 100644 --- a/components/editor/color-picker.tsx +++ b/components/editor/color-picker.tsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback, useEffect } from "react"; +import React, { useState, useEffect, useMemo } from "react"; import { Label } from "@/components/ui/label"; import { ColorPickerProps } from "@/types"; import { debounce } from "@/utils/debounce"; @@ -12,13 +12,9 @@ const ColorPicker = ({ color, onChange, label }: ColorPickerProps) => { setLocalColor(color); }, [color]); - // Create debounced onChange handler with useCallback to maintain reference - const debouncedOnChange = useCallback( - (value: string) => { - debounce(() => { - onChange(value); - }, 10)(); - }, + // Create a stable debounced onChange handler + const debouncedOnChange = useMemo( + () => debounce((value: string) => onChange(value), 20), [onChange] ); @@ -28,6 +24,13 @@ const ColorPicker = ({ color, onChange, label }: ColorPickerProps) => { debouncedOnChange(newColor); }; + // Cleanup debounced function on unmount + useEffect(() => { + return () => { + debouncedOnChange.cancel(); + }; + }, [debouncedOnChange]); + return (
diff --git a/utils/debounce.ts b/utils/debounce.ts index 672bbea2..985580b4 100644 --- a/utils/debounce.ts +++ b/utils/debounce.ts @@ -1,10 +1,19 @@ -export function debounce(fn: (...args: any[]) => void, delay: number) { +export function debounce void>( + fn: T, + delay: number +): T & { cancel: () => void } { let timeoutId: NodeJS.Timeout; - return function (...args: any[]) { + + const debounced = function (this: unknown, ...args: Parameters) { clearTimeout(timeoutId); timeoutId = setTimeout(() => { - // @ts-expect-error: it works fn.apply(this, args); }, delay); + } as T & { cancel: () => void }; + + debounced.cancel = () => { + clearTimeout(timeoutId); }; + + return debounced; }