Reactjs中setTimeout未按预期工作,延迟函数在组件渲染时立即执行
核心错误点
- 传参时直接执行了
alert语句:alert("Inactive for 5 seconds")会在代码解析到这一行的时候立即运行,返回值是undefined,相当于你给setTimeout传的回调是undefined,自然达不到延迟执行的效果。 - 逻辑放在了
render方法中:render函数会在每次组件重渲染时都执行,会导致重复绑定DOM事件、重复创建定时器,引发逻辑异常和内存泄漏。
修复后的完整代码
class App extends React.Component { // 存储定时器ID、延迟时长、闲置回调,方便后续管理 waitTimer = null; delayMs = null; inactiveCallback = null; // 单独抽离活跃事件处理函数,方便后续解绑 handleUserActive = () => { clearTimeout(this.waitTimer); this.waitTimer = setTimeout(this.inactiveCallback, this.delayMs); }; onInactive = (ms, cb) => { this.delayMs = ms; this.inactiveCallback = cb; this.waitTimer = setTimeout(cb, ms); // 绑定用户活跃相关的DOM事件 document.onmousemove = document.onmousedown = document.onmouseup = document.onkeydown = document.onkeyup = document.onfocus = this.handleUserActive; }; componentDidMount() { // 组件挂载完成后仅初始化一次闲置检测 // 把alert包裹为匿名函数,仅在定时器触发时执行 this.onInactive(5000, () => alert("Inactive for 5 seconds")); } componentWillUnmount() { // 组件卸载前清理定时器、解绑DOM事件,避免内存泄漏 clearTimeout(this.waitTimer); document.onmousemove = document.onmousedown = document.onmouseup = document.onkeydown = document.onkeyup = document.onfocus = null; } render() { return ( <div className="App"> <h1>Hello CodeSandbox</h1> <h2>Start editing to see some magic happen!</h2> </div> ); } } export default App;
关键点说明
- 延迟执行的回调必须传入函数引用,如果需要传参可以包裹为匿名函数,比如
() => 你的执行语句,不要直接写执行语句。 - DOM事件绑定、定时器这类副作用逻辑不要放在
render方法中,放在componentDidMount这类生命周期函数中保证仅执行必要的次数,同时要在组件卸载前做清理。
内容的提问来源于stack exchange,提问作者yongchang
相关产品推荐
相关产品推荐

