React中setInterval的正确调用位置及计数器实现错误排查
问题分析
第一种写法的问题
- 你定义的
increment方法全程没有被调用过,方法内部的setInterval永远不会执行,计数器自然不会更新 - 即使后续补上
increment的调用逻辑,重复调用会生成多个定时器,导致计数速度异常,且组件卸载后定时器不会自动清除,会造成内存泄漏 - 你在
setState里直接读取this.state.counter计算新值,当存在批量状态更新时很容易出现计数异常,不符合React状态更新的最佳实践
第二种写法的问题
increment是类实例的实例方法,不是类的静态方法,直接用Counter.increment访问不到这个方法,拿到的是undefined,定时器不会执行任何有效逻辑- 就算你拿到了组件实例的
increment方法,直接传给setInterval的话,方法执行时this会指向全局对象,不是组件实例,调用this.setState会直接报错 - 全局定义的定时器和组件实例完全脱钩,组件卸载后定时器仍会运行,同样存在内存泄漏问题
- 你设置的100ms间隔和常规的1秒计数需求也不符
正确实现方案
定时器逻辑要和组件生命周期绑定,挂载完成后启动定时器,卸载前主动清除定时器,状态更新使用函数式写法保证取值正确,完整代码如下:
class Counter extends React.Component { state = { counter: 0 } // 存储定时器ID,用于后续清除 timerId = null; componentDidMount() { // 组件挂载完成后启动1秒间隔的定时器 this.timerId = setInterval(() => { // 使用函数式更新,保证拿到的是上一次的最新状态 this.setState(prevState => ({ counter: prevState.counter + 1 })); }, 1000); } componentWillUnmount() { // 组件卸载前清除定时器,避免内存泄漏 clearInterval(this.timerId); } render() { return <div> <p>{this.state.counter}</p> </div>; } } ReactDOM.render( <Counter />, document.getElementById('root') );
内容的提问来源于stack exchange,提问作者nfn
相关产品推荐
相关产品推荐

