useEffect内包含条件判断setTimeout的下述代码写法是否正确?
问题代码缺陷分析
这段代码存在两处明显逻辑问题,不能直接投入生产使用,具体问题如下:
第一:依赖数组设置错误引发闭包问题
你当前给useEffect传入了空依赖数组[],这意味着这个effect只会在组件首次挂载完成后执行1次,内部用到的condition、func1、func2都只会捕获首次渲染时的快照值。后续哪怕这几个值发生了更新,effect内部拿到的永远是旧值,完全不会响应状态变化,大概率会出现不符合预期的逻辑错误。
按照React Hooks官方规则,所有在effect内部用到的外部变量,都需要加入依赖数组,如果你确定要忽略部分依赖,也要明确标注注释说明原因,避免后续维护踩坑。第二:定时器清理逻辑存在泄漏隐患
你把定时器的清理函数写在了if(condition)的分支内,只有首次执行时condition为真的情况下,effect才会返回清理定时器的函数;如果首次执行condition为真已经创建了定时器,后续依赖更新触发effect重新执行、或者组件卸载时condition变成了假,此时effect返回的是空函数,之前创建的定时器就不会被清理,轻则内存泄漏,重则定时器触发时调用已卸载组件的方法,抛出React运行时警告。
整改参考写法
useEffect(() => { let timer = null if (condition) { timer = setTimeout(() => { func1() }, 1000) } func2() // 清理函数统一写在最外层,无论condition取值如何都能正确清理定时器 return () => { if(timer) clearTimeout(timer) } // 所有用到的外部变量都加入依赖数组 }, [condition, func1, func2])
额外优化提示:如果
func1、func2是在组件内部定义的函数,建议用useCallback包裹后再传入依赖数组,避免不必要的effect重复执行。
内容的提问来源于stack exchange,提问作者Moon
相关产品推荐
相关产品推荐

