正如Vasanth所提到的,我更喜欢:
import { useEffect, useRef } from 'react';
export const useInterval = (
callback: Function,
fnCondition: Function,
delay: number,
) => {
const savedCallback = useRef<Function>();
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
useEffect(() => {
let id: NodeJS.Timeout;
const tick = async () => {
try {
const response =
typeof savedCallback.current === 'function' &&
(await savedCallback.current());
if (fnCondition(response)) {
id = setTimeout(tick, delay);
} else {
clearTimeout(id);
}
} catch (e) {
console.error(e);
}
};
tick();
return () => id && clearTimeout(id);
}, [delay]);
};
作用:使用内部的 fnCondition,其中可以是基于上一个请求响应的条件。
const {
data,
isLoadingData,
getData,
} = api.useGetData();
const fnCondition = (result: any) => {
const randomContidion = Math.random();
return randomContidion < 0.9;
};
useInterval(() => getData(), fnCondition, 1000);
无法使用:像这样将
延迟传递为
null以停止
useInterval对我来说不起作用,使用以下代码:
https://www.aaron-powell.com/posts/2019-09-23-recursive-settimeout-with-react-hooks/(您可能会有这种印象,但在启动/停止几次后它会出现问题)。
const [isRunning, setIsRunning] = useState(true);
const handleOnclick = () => {
setIsRunning(!isRunning);
};
useInterval(() => getData(), isRunning ? 1000 : null);
<button onClick={handleOnclick}>{isRunning ? 'Stop' : 'Start'}</button>
总结:我可以通过传递fnCondition来停止useInterval的使用,但无法通过传递delay=null来停止使用。