首頁  >  問答  >  主體

使用React中的防手震hooks的方法

import { useEffect, useState } from 'react';

export default function useDebounce(text: string, delay: number) {
  const [value, setValue] = useState('');

  useEffect(() => {
    const timerId = setTimeout(() => {
      setValue(text);
    }, delay);
    return () => {
      clearTimeout(timerId);
    };
  }, [text, delay]);
  return value;
}


我曾經製作和使用 useDebounce 鉤子。 但是,在調整大小事件中使用 useDebounce 存在一些問題。 useDebounce hook 必須在元件頂部運行,因為它在內部使用了 useEffect。 但是,調整大小函數設定為在 useEffect 上運行,如下所示。

此外,上面的程式碼將值作為一個因素,但我認為我們需要接收它作為回調才能使用下面的程式碼。

  useEffect(() => {
    const handler = () => {
      if (liRef.current) setWidth(liRef.current.clientWidth);
    };

    window.addEventListener('resize', handler);
    return () => window.removeEventListener('resize', handler);
  }, []);

如何使用上面的程式碼來利用現有的useDebounce?

P粉497463473P粉497463473236 天前378

全部回覆(2)我來回復

  • P粉098417223

    P粉0984172232024-01-29 11:40:03

    如果你直接在React元件中使用debounced函數,它將不起作用,因為每個渲染都會建立一個新函數,相反,你可以使用這個useDebounce鉤子:

    function useDebounce(callback, delay) {
      const callbackRef = React.useRef(callback)
      React.useLayoutEffect(() => {
        callbackRef.current = callback
      })
      return React.useMemo(
        () => debounce((...args) => callbackRef.current(...args), delay),
        [delay],
      )
    }
    

    useRef 確保它與上次提供的函數相同,並且 useLayoutEffect 確保在每次渲染時,對函數的引用都會更新。

    有關這方面的更多信息,請參閱“最新參考”模式反應

    回覆
    0
  • P粉894008490

    P粉8940084902024-01-29 09:59:42

    我認為與其透過useEffect實現去抖,不如將去抖邏輯實作為一個函數。

    useEffectdeps 引用的狀態改變時執行。也就是說,由於是一個如果只按照執行流程就容易漏掉的邏輯,所以後期維護時很難弄清楚這個useEffect是從哪一個流程衍生出來的,調試起來也比較困難。

    範例

    自訂反跳

    #
    function debounce(func, timeout = 300) {
      let timer;
      return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(this, args);
        }, timeout);
      };
    }
    
    function saveInput() {
      console.log('Saving data');
    }
    const processChange = debounce(() => saveInput());
    
    
    

    如果您使用lodash,則只需匯入即可使用它。

    Lodash Debounce

    import { debounce } from 'lodash';
    
    const debounceOnChange = debounce(() => {
      console.log("This is a debounce function");
    }, 500);
    

    希望這有幫助:)

    回覆
    0
  • 取消回覆