React如何无触发事件正确调用setState实现定时状态更新
报错根源
你把setTimeout调用直接写在了类体的顶层位置,ES6类的内部只允许声明方法、类属性、静态成员这类结构,直接放可执行的函数调用语句不符合类语法规范,就会抛出unexpected token语法错误。
除此之外你的代码还有两个运行时问题:
- 普通
function声明的回调里this默认不指向组件实例,严格模式下是undefined,根本访问不到this.setState和this.state,就算语法通过运行也会报错 setTimeout是单次延迟执行的API,你需要每隔固定时间循环更新计数,应该用setInterval实现
正确实现代码
类组件里做定时自动更新状态,要借助生命周期方法控制定时器的启动和销毁,避免内存泄漏,完整代码如下:
class Counter extends React.Component { constructor(props) { super(props); this.state = { myCount: 1 }; // 存储定时器ID,用于后续清除 this.timer = null; } componentDidMount() { // 组件完成挂载后启动15秒间隔的循环定时器 this.timer = setInterval(() => { // 箭头函数自动绑定组件实例this,函数式更新保证拿到最新的state值 this.setState(prev => ({ myCount: prev.myCount + 1 })); }, 15000); } componentWillUnmount() { // 组件卸载前清除定时器,避免内存泄漏和卸载后更新状态的警告 clearInterval(this.timer); } render() { return <div>当前计数:{this.state.myCount}</div> } }
关键注意点
- 所有副作用(包括定时器、网络请求这类操作)都要放在
componentDidMount生命周期里执行,不要直接写在类体或者constructor里 - 定时器回调优先用箭头函数,自动绑定当前组件实例的
this指向,不需要手动调用bind修改指向 - 当新状态依赖旧状态的值时,必须给
setState传入更新函数,通过入参拿到最新的前序状态,避免闭包缓存旧值导致计数错误 - 定时器这类会持续执行的任务,必须在组件卸载的生命周期里清除,否则组件销毁后任务还在后台运行,会造成内存泄漏
内容的提问来源于stack exchange,提问作者Real Noob
相关产品推荐
相关产品推荐

