React类组件页面加载自动启动倒计时this.setState报错排查
React类组件倒计时报错排查与修复
核心问题点
setInterval回调的this指向错误:传入的普通function声明的回调执行时上下文指向全局对象(严格模式下为undefined),并非组件实例,因此无法找到setState方法触发报错。- 渲染阶段状态读取方式错误:类组件的状态统一存储在
this.state对象中,直接通过this.days、this.hours这类写法无法读取到状态值,页面会渲染空内容。 - 缺少定时器清理逻辑:组件卸载后如果不手动清除定时器,定时器会持续在后台运行,既会造成内存泄漏,还可能触发「对已卸载组件执行setState」的警告。
修复后完整代码
import React,{Component} from "react"; class Countdown extends Component{ constructor(props){ super(props); this.state={ days:30, hours:720, minutes:59, seconds:59 } // 存储定时器ID的实例属性 this.timer = null; } componentDidMount(){ const countDownDate = new Date("Jul 30, 2022 11:00:00").getTime(); // 箭头函数回调会继承外层组件实例的this指向,可正常调用setState this.timer = setInterval(() => { const now = new Date().getTime(); const timeleft = countDownDate - now; // 倒计时结束时自动清除定时器,避免显示负数 if (timeleft < 0) { clearInterval(this.timer); this.setState({ days:0, hours:0, minutes:0, seconds:0 }) return; } this.setState({ days: Math.floor(timeleft / (1000 * 60 * 60 * 24)), hours : Math.floor((timeleft % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)), minutes: Math.floor((timeleft % (1000 * 60 * 60)) / (1000 * 60)), seconds: Math.floor((timeleft % (1000 * 60)) / 1000), }) } , 1000); } componentWillUnmount() { // 组件卸载时清除定时器,避免内存泄漏 if (this.timer) clearInterval(this.timer); } render(){ // 从this.state中解构读取状态值 const { days, hours, minutes, seconds } = this.state; return ( <div> <p>{days}天</p> <p>{hours}时</p> <p>{minutes}分</p> <p>{seconds}秒</p> </div> ) } } export default Countdown;
可选替代方案
如果不想用箭头函数,也可以在constructor中提前对回调函数做this绑定,或者用.bind(this)修改回调执行上下文,箭头函数是日常开发中最简洁的写法。
内容的提问来源于stack exchange,提问作者madQuestions
相关产品推荐
相关产品推荐

