在React中寻求可重启的超时钩子

问题描述 投票:0回答:1

我正在构建一个显示图像的应用程序。 在每个图像的顶部,我希望显示一个信息丰富的工具提示,但是当鼠标移到图像顶部时,我希望工具提示仅在大约 0.5 秒后显示。

为此,我实现了这个React Hook:

import * as React from 'react';

/**
 * This is a React Hook implementation of the window.setTimeout function.
 * Source: https://www.joshwcomeau.com/snippets/react-hooks/use-timeout
 * 
 * @param {callback} onTimerDone 
 * @param {number} delay - milliseconds
 */
export const useTimeout = (onTimerDone: () => void, delay: number) => {
  const timeoutRef = React.useRef(0);
  const savedCallback = React.useRef(onTimerDone);

  React.useEffect(() => {
    savedCallback.current = onTimerDone;
  }, [onTimerDone]);
  
  React.useEffect(() => {
    const tick = () => savedCallback.current();
    timeoutRef.current = window.setTimeout(tick, delay);

    return () => window.clearTimeout(timeoutRef.current); // Cleanup function
  }, [delay]);

  return timeoutRef;
};

我尝试了几种方法,但只能让这个计时器钩子触发一次。 我正在寻找一个类似于可重新启动计时器的计时器。 换句话说,只要我指示,计时器就会一次又一次地开始倒计时。

我不知道如何实现一个按我需要的方式工作的超时挂钩。 谁能提供一些建议吗?

reactjs typescript timer
1个回答
0
投票

如果您需要在超时后显示工具提示,您需要使用事件处理程序,而不是

useEffect

// reusable hook to schedule timeouts
function useTimeoutTask() {
  const timer = useRef<ReturnType<typeof setTimeout>>();

  const cancel = useCallback(() => {
    if (timer.current) {
      clearTimeout(timer.current);
      timer.current = undefined;
    }
  }, []);

  const schedule = useCallback((handler: () => void, timeout: number) => {
    // we only allow one active timeout at a time
    cancel();

    timer.current = setTimeout(handler, timeout);
  }, []);

  // Clear timeout on unmount
  useEffect(() => () => cancel(), []);

  return {
    schedule,
    cancel,
  };
}

// and example of application
function useTooltip() {
  const [showTooltip, setShowTooltip] = useState(false);
  const { cancel, schedule } = useTimeoutTask();

  const onMouseEnter = () => {
    // setup task inside event handler
    schedule(() => {
      setShowTooltip(true);
    }, 500);
  };

  const onMouseLeave = () => {
    // cancel tooltip in case mouse leaves before tooltip was shown
    cancel();
    setShowTooltip(false);
  };
}
© www.soinside.com 2019 - 2024. All rights reserved.