React中setTimeout应该在哪里清除?两种写法差异及正确实践是什么
React两种setTimeout写法的区别与最佳实践
写法对比
第一种写法
useEffect(() => { const id_1 = setTimeout(() => { // do something clearTimeout(id_1); }, 500); }, [success_failure_msg[0]]);
第二种写法
useEffect(() => { const id_1 = setTimeout(() => { // do something }, 500); return () => clearTimeout(id_1); }, [success_failure_msg[0]]);
核心区别
两种写法的清理逻辑触发时机完全不同:
- 第一种的
clearTimeout写在定时器回调内部,只有定时器正常到期执行回调的时候才会触发清理。如果在500ms到期前,依赖项success_failure_msg[0]发生变化导致effect重新执行,或者组件直接卸载,这个定时器不会被清理,仍然会在到期后执行回调逻辑。 - 第二种的
clearTimeout写在useEffect返回的清理函数中,所有可能的销毁场景都会触发清理:要么是依赖变化导致effect重新执行前,要么是组件卸载前,都会先执行清理函数把未执行的定时器销毁,不会出现漏清理的情况。
正确开发实践
第二种写法是标准的正确实践。
第一种写法存在明确的内存泄漏和逻辑异常风险:比如用户在定时器触发前就切走了页面,组件已经卸载,第一种写法的定时器到期后如果回调里有修改组件状态的操作,就会抛出React的未挂载组件更新状态警告,甚至引发业务逻辑错误。
只有在极端场景下能100%保证定时器到期前effect不会重跑、组件不会卸载,第一种写法才不会出问题,但这种场景在实际开发中几乎不存在,所以完全不推荐使用第一种写法。
内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture
相关产品推荐
相关产品推荐

