我正在构建一个显示图像的应用程序。 在每个图像的顶部,我希望显示一个信息丰富的工具提示,但是当鼠标移到图像顶部时,我希望工具提示仅在大约 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;
};
我尝试了几种方法,但只能让这个计时器钩子触发一次。 我正在寻找一个类似于可重新启动计时器的计时器。 换句话说,只要我指示,计时器就会一次又一次地开始倒计时。
我不知道如何实现一个按我需要的方式工作的超时挂钩。 谁能提供一些建议吗?
如果您需要在超时后显示工具提示,您需要使用事件处理程序,而不是
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);
};
}