簡體   English   中英

是否可以在 React 中制作“useIsAnimating”鈎子?

[英]Is it possible to make a `useIsAnimating` hook in React?

所以我在我的 React 應用程序中有一個功能,它可以非常有用地知道一個元素是否正在動畫/通過關鍵幀。

昨天我花了一整天時間通過類似下面的東西和許多其他抽象來嘗試大量的迭代,但似乎無法讓它工作。 有什么想法,或者這是不可能的嗎?

function useIsAnimating(ref) {
  const [isAnimating, setIsAnimating] = React.useState(false);

  useEffect(() => {
    ref?.current.addEventListener('animationstart', setIsAnimating(true)); 
    ref?.current.addEventListener('animationend', setIsAnimating(false)); 
    
    return () => {      
    ref?.current.removeEventListener('animationstart', setIsAnimating(true)); 
    ref?.current.removeEventListener('animationend', setIsAnimating(false)); 
    };
  }, [ref, setIsAnimating]);

  return isAnimating;
}

無需過多說明您想要這樣做的原因,上面的代碼有一個簡單的問題。

addEventListener期望的第二個參數是 function,它應該在觸發給定事件時調用。 您的代碼沒有這樣做,而是這樣做(在將其擴展為更易讀的形式之后):

const animationStartListener = setIsAnimating(true);
ref?.current.addEventListener('animationstart', animationStartListener);
const animationEndListener = setIsAnimating(false);
ref?.current.addEventListener('animationend', animationEndListener);

為了使您的代碼正常工作,您必須setIsAnimating(true)的調用包裝在 function 中,並將 function 作為參數傳遞給addEventListener

const animationStartListener = () => setIsAnimating(true);
ref?.current.addEventListener('animationstart', animationStartListener);
const animationEndListener = () => setIsAnimating(false);
ref?.current.addEventListener('animationend', animationEndListener);

或者,使用更短的語法:

ref?.current.addEventListener('animationstart', () => setIsAnimating(true));
ref?.current.addEventListener('animationend', () => setIsAnimating(false));

要記住的另一件事是,當您刪除偵聽器時,您必須將相同的引用傳遞給 function ,就像傳遞給addEventListener一樣。 在 React 中使用 React Hooks 的正確方法是使用useCallback鈎子:

function useIsAnimating(ref) {
  const [isAnimating, setIsAnimating] = React.useState(false);
  const handleAnimationStart = useCallback(
    () => setIsAnimating(true),
    [setIsAnimating],
  );
  const handleAnimationEnd = useCallback(
    () => setIsAnimating(false),
    [setIsAnimating],
  );

  useEffect(() => {
    ref?.current.addEventListener('animationstart', handleAnimationStart); 
    ref?.current.addEventListener('animationend', handleAnimationEnd); 
    
    return () => {      
    ref?.current.removeEventListener('animationstart', handleAnimationStart); 
    ref?.current.removeEventListener('animationend', handleAnimationEnd); 
    };
  }, [ref, handleAnimationStart, handleAnimationEnd]);

  return isAnimating;
}

希望這可以幫助您解決問題(我在這里沒有犯任何拼寫錯誤)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM