Este es mi propio gancho que se usa para realizar debounce en React Hooks
import { useMemo, useRef } from "react"; import { debounce } from "lodash"; export function useDebounceFn(fn, wait) { const fnRef = useRef(fn) fnRef.current = () => { debugger fn() } const debounceFn = useMemo(() => { // Case One: can get the newest fn everytime return debounce(() => { fnRef.current() }); // Case Two: only can get the first fn return debounce(fnRef.current); }, []); return { run: debounceFn, cancel: debounceFn.cancel, } } Creo que debounce(fnRef.current) es igual a debounce(() => { fnRef.current() }) , pero la verdad es que son diferentes y me pregunto por qué. ¿Hay algún problema con mi código o simplemente useMemo para hacer algo diferente en estos dos casos?
const { run } = useDebounceFn(() => { console.log("num", num); }); useEffect(() => { run(); }, [num]); Cuando uso el caso uno, puedo obtener el número más num y esto es lo que quiero darme cuenta, pero cuando uso el caso dos, cada run la función de ejecución solo puede obtener el num . Quiero saber por qué el caso dos solo puede obtener el valor inicial, en otras palabras, por qué el caso uno siempre puede obtener el valor más nuevo en useMemo .
Creo que
debounce(fnRef.current)es igual adebounce(() => { fnRef.current() }), pero la verdad es que son diferentes y me pregunto por qué.
run devuelta, el valor de referencia actual se "desempaqueta". Puede solucionar el caso 2 completando la matriz de dependencias del gancho useMemo para volver a encerrar el valor de referencia actual.
Ejemplo:
export function useDebounceFn(fn, wait) { const fnRef = useRef(fn); const debounceFn = useMemo(() => { // Re-"cache" the function fnRef.current = () => { debugger fn() } // Re-decorate with debounce HOF return debounce(fnRef.current); }, [fn]); return { run: debounceFn, cancel: debounceFn.cancel, } } Por cierto, para el caso 1, debe usar un gancho useEffect para establecer el valor de referencia cuando se actualice fn .
Ejemplo:
export function useDebounceFn(fn, wait) { const fnRef = useRef(fn); useEffect(() => { fnRef.current = () => { debugger fn(); } }, [fn]); const debounceFn = useMemo(() => { return debounce(() => { fnRef.current(); }); }, []); return { run: debounceFn, cancel: debounceFn.cancel, } }