async function like(cleanups: (() => void)[] ) {
const a = await delay(2000) // 等待一些异步操作
if(a) {
const clearId = setInterval(play, 2000);
cleanups.push(() => {
clearInterval(clearId);
});
}
}
useEffect(() => {
const cleanups: (() => void)[] = [];
like(cleanups);
function clean() {
cleanups.forEach((cleanup) => {
cleanup();
});
}
return clean
}, [status, interval]); // 删除了部分 status, interval 的依赖逻辑
以上的代码如果在 StrictMode 模式下运行就会发现有一个定时器没有被移除,这也表明其实以上的代码是有问题的。如果依赖项快速变化,那么会有越来越多的定时器没有被移除,原因是 cleanups 的收集是异步的,在没有收集到定时器前,可能 clean 就执行了,导致了之后收集的定时器并没有被移除。如何在保持一样的功能下修复上面的问题?
可以使用一个 useRef 来存储当前的定时器 ID,并在 useEffect 清理函数中立即清理它。
以下是修复后的代码:
使用 useRef 来存储当前的清理函数,并在每次 useEffect 执行时立即清理之前的定时器。这确保了即使在依赖项快速变化的情况下,定时器也能被正确清理。这样可以避免定时器泄漏的问题。