React中双定时器无法正常执行 求实现循环倒计时流程
问题修复:循环倒计时与输入框显示流程
核心错误梳理
- CountDown组件render语法错误:
return后直接换行触发JS自动分号插入,导致组件无渲染内容,控制台报错。 - componentDidUpdate参数错误:该方法第一个参数是
prevProps,第二个才是prevState,原代码把prevProps当成prevState使用,导致倒计时结束的判断逻辑失效。 - CountDown无重置机制:父组件状态变化重新传入
duration时,组件不会重置倒计时数值,无法实现循环触发。 - App组件语法与逻辑漏洞:
- JSX缺少根包裹元素,语法报错;
onChange函数未定义;- 状态更新是异步的,直接打印
canType会拿到旧值; - 无循环重启timer1的逻辑,timer2结束后流程终止。
修复后的完整代码
CountDown.js
import React from 'react'; export default class CountDown extends React.Component { constructor(props) { super(props); this.state = { count: props.duration ?? 5, } } // 监听props变化,重置倒计时 static getDerivedStateFromProps(nextProps, prevState) { if (nextProps.duration !== prevState.count) { return { count: nextProps.duration }; } return null; } componentDidMount() { this.startTimer(); } componentDidUpdate(prevProps, prevState) { // 倒计时结束时清除定时器并触发回调 if (prevState.count !== this.state.count && this.state.count === 0) { clearInterval(this.timer); this.props.onTimesup?.(); } // 当props的duration变化时,重启定时器 if (prevProps.duration !== this.props.duration) { clearInterval(this.timer); this.startTimer(); } } componentWillUnmount() { clearInterval(this.timer); // 组件卸载时清除定时器,避免内存泄漏 } startTimer() { this.timer = setInterval(() => { this.setState(prevState => ({ count: prevState.count - 1 })); }, 1000); } fmtMSS(s) { const minutes = Math.floor(s / 60); const seconds = s % 60; return `${minutes}:${seconds.toString().padStart(2, '0')}`; } render() { const { count } = this.state; return <div>{this.fmtMSS(count)}</div>; } }
App.js
import React, { useState } from 'react'; import CountDown from './CountDown'; const App = () => { const [canType, setCanType] = useState(0); const [restartKey, setRestartKey] = useState(0); const onTimer1End = () => { setCanType(1); setTimeout(() => console.log("timer1 结束,canType:", canType), 0); }; const onTimer2End = () => { setCanType(0); setTimeout(() => { console.log("timer2 结束,canType:", canType); // 通过修改key强制重启timer1 setRestartKey(prev => prev + 1); }, 0); }; const onChange = (e) => { console.log("输入内容:", e.target.value); }; return ( <div className="box d"> {canType === 0 && ( <CountDown key={restartKey} onTimesup={onTimer1End} duration={2} /> )} {canType === 1 && ( <> <input type="text" onChange={onChange} /> <CountDown onTimesup={onTimer2End} duration={5} /> </> )} </div> ); }; export default App;
修复说明
- CountDown组件:
- 新增
getDerivedStateFromProps监听duration变化,重置倒计时数值; - 提取
startTimer方法复用定时器启动逻辑; - 修复
componentDidUpdate参数顺序,确保判断逻辑正确; - 新增
componentWillUnmount清除定时器,避免内存泄漏; - 修复render方法的语法错误,添加倒计时文本渲染。
- 新增
- App组件:
- 通过修改
key强制重启timer1,实现循环流程; - 补充
onChange函数,避免控制台报错; - 用
setTimeout异步打印最新状态,解决异步更新的旧值问题; - 用
<>包裹同级JSX元素,修复根元素问题。
- 通过修改
内容的提问来源于stack exchange,提问作者Venoz
相关产品推荐
相关产品推荐

