React useEffect场景下clearTimeout取消定时器不生效问题求助
问题根因
你的代码存在三个核心逻辑漏洞,导致快速切换hover场景下状态异常:
removeCursor中错误添加了if (timerRef.current === null) return判断,定时器执行完成后不会自动重置timerRef为null,部分场景下合法的重置光标逻辑会被意外拦截- 所有定时器执行完成后没有手动重置
timerRef.current为null,产生状态残留,干扰后续逻辑判断 - 快速跨box移动时,hover状态会先变空触发
removeCursor开启500ms定时器,再变回非空触发addCursor,原有逻辑虽然会清定时器,但10ms的延迟设置wait光标容易和残留的重置逻辑产生错位
修正方案
const [hoverItem, setHoverItem] = useState(null) const timerRef = useRef(null) const addCursor = useCallback(() => { // 先清除所有待执行的定时器,不管是重置光标的还是设置光标的 clearTimeout(timerRef.current) timerRef.current = null // 没有特殊需求可以直接设置光标,去掉10ms延迟避免状态错位 document.body.style.cursor = 'wait' // 如果必须保留10ms延迟,替换为下面的代码即可 // timerRef.current = setTimeout(() => { // document.body.style.cursor = 'wait' // timerRef.current = null // }, 10) }, []) const removeCursor = useCallback(() => { // 先清除已有定时器,避免多次触发生成多份异步任务 clearTimeout(timerRef.current) timerRef.current = null // 开启500ms延迟重置光标 timerRef.current = setTimeout(() => { document.body.style.cursor = 'default' timerRef.current = null }, 500) }, []) useEffect(() => { if (hoverItem) { addCursor() } else { removeCursor() } // 组件卸载时清除定时器,避免内存泄漏 return () => clearTimeout(timerRef.current) }, [hoverItem, addCursor, removeCursor])
逻辑说明
- 每次触发设置/重置光标逻辑时,都会先清空所有待执行的定时器,保证同一时间只有一个异步任务在队列中
- 定时器执行完成后主动重置
timerRef为null,消除状态残留 - 移除了冗余的状态判断逻辑,避免合法逻辑被拦截
- 新增了组件卸载时的定时器清理逻辑,避免内存泄漏
修正后完全满足你的两个需求:
- 鼠标移出box区域后,光标会保持500ms的wait状态再恢复默认
- 快速在多个box之间移动时,只要最终停在box上,中间触发的重置光标定时器会被立即清除,始终保持wait光标显示
内容的提问来源于stack exchange,提问作者Evan Jin
相关产品推荐
相关产品推荐

