Estaba tratando de implementar la funcionalidad de rebote en React dentro de useEffect. Aunque para el siguiente código, si llamo a debounceFunc , se ejecuta solo una vez, mientras que si llamo directamente a debounceFunc3 no funciona.
const handleClick = () => { setEvent((pre) => [...pre, 1]); }; const delayFunc = () => { let timer; return function () { clearTimeout(timer); timer = setTimeout(() => console.log("Hello timer 1"), 2000); }; }; const delayFunc3 = useCallback(() => { let timer3; return function () { clearTimeout(timer3); timer3 = setTimeout(() => console.log("Hello timeout3"), 2000); }; }, []); const debounce = useCallback(delayFunc(), []); useEffect(() => { if (event?.length > 0) { debounce(); delayFunc3()(); } }, [event]); En la consola, Hello timer 1 se imprime solo una vez, mientras que Hello timeout3 se imprime o cada evento se activa/cambia.
Enlace de Codebox para jugar:
https://codesandbox.io/s/inspiring-lamport-sbbup?file=/src/App.js:0-872
No pude entender qué tiene de malo la forma en que estoy llamando a debounceFunc3
El problema con su código es que está ejecutando delayFunc3() varias veces:
delayFunc3()(); El problema con esto es que cada vez que llamas a delayFunc3()() estás creando una nueva variable local timer3 dentro de tu función delayFunc3 y luego ejecutando la función devuelta que ahora hace referencia a esa nueva variable local timer3 .
Esto significa que si llamas a delayFunc3()(); , primero se crea una nueva variable timer3 y luego se ejecuta la función devuelta, poniendo en cola un nuevo tiempo de espera.
Si luego llamas a delayFunc3()(); , nuevamente, se crea una nueva variable timer3 (se inicializa en undefined ), y luego se ejecuta la función devuelta. Cuando se ejecuta su función devuelta, está ejecutando clearTimeout(timer3); , que no borrará ningún temporizador ya que timer3 aquí se refiere a la nueva variable timer3 que se inicializó y no está undefined , y no al timer3 anterior que se creó en la llamada anterior a la función delayFunc3()() .
Como resultado, llamar a delayFunc3()(); nuevamente, mientras su primer tiempo de espera aún se está ejecutando, no tendrá ningún efecto en el primer tiempo de espera, ya que el timer3 creado por esta invocación no tiene relación con el timer3 anterior creado, por lo que no se borrará.
A diferencia de esto, realizando lo siguiente:
const debounce = useCallback(delayFunc(), []); ejecuta su delayFunc() y crea un nuevo timer variable local dentro del alcance de delayFunc() . La función devuelta por delayFunc() se cierra sobre la variable de timer declarada dentro del alcance de delayFunc() . Esto significa que siempre que se debounce() , no creará una nueva variable de timer como en el primer ejemplo, sino que reutilizará el timer creado a partir de la llamada inicial de delayFunc() . Cada llamada a debounce() reutilizará la misma variable de timer , por lo que, si se debounce() a llamar a debounce(), clearTimeout(timer); borrará el temporizador en cola previamente.
También tenga en cuenta que en ambos ejemplos, está usando useCallback() en dos cosas diferentes. Con debounce , está llamando a useCallback() en la función devuelta de delayFunc() . Esto significa que todas las representaciones futuras de su componente utilizarán la única referencia de función que se devolvió desde la llamada inicial de delayFunc() cuando se montó su componente. Por lo tanto, el debounce se refiere a la función única para todos los renderizados.
A diferencia de esto, delayFunc3 usa useCallback() no en la función devuelta, sino en toda la función (es decir, la función de flecha "principal"). Esto significa que cada renderizado de su componente usará la misma función "principal", pero esa función principal aún crea una nueva variable timer3 cuando se invoca y devuelve una nueva función interna cada vez que se llama.