React中useEffect钩子内setTimeout定时器无法正常清除问题咨询
你代码的核心错误点
- 所有useEffect都没有传入依赖数组,导致每次组件渲染都会重新执行useEffect逻辑,反复创建新的定时器,之前的定时器ID丢失根本无法清除
clearTimeout必须传入要清除的定时器ID,不传参数的调用没有任何效果- 定时器的清理函数被你加了
introDisplayed === true的判断限制,实际上useEffect的清理函数需要每次执行副作用前都清理上一次的定时器,不需要加额外判断 - 缺少当前路由判断,你只需要在
/home页才开启这个自动跳转逻辑,否则所有页面都生效会出现逻辑混乱
正确实现方案
const Page = ({ introDisplayed, setIntroDisplayed }) => { const history = useHistory() const location = useLocation() useEffect(() => { // 仅在/home页、引导未展示的场景下开启定时器 if (location.pathname === '/home' && !introDisplayed) { const timer = setTimeout(() => { setIntroDisplayed(true) history.push("/about") }, 5000) // 无论什么场景,只要useEffect重执行/组件卸载,都清理当前定时器 return () => clearTimeout(timer) } // 所有用到的外部变量都加入依赖数组 }, [location.pathname, introDisplayed, setIntroDisplayed, history]) // 此处保留你原有的组件渲染逻辑 return <></> }
逻辑验证
用户手动点击链接时introDisplayed会被设为true,触发useEffect重新执行,上一次的定时器会被直接清理,不会再执行跳转逻辑;如果用户停留在/home页满5秒,定时器正常执行跳转到/about,后续也不会重复触发。
内容的提问来源于stack exchange,提问作者sudo_xvx
相关产品推荐
相关产品推荐

