如何使用Day.js实现10分钟倒计时,结束后将isValid从true改为false
问题解决方法
核心问题说明
原有代码的问题如下:
- 直接将系统当前时间的分、秒赋值给展示状态,没有计算10分钟后目标时间与当前时间的差值,无法实现倒计数效果
- 时间计算逻辑冗余,Day.js内置了
diff方法可以直接计算两个时间点的毫秒差,不需要手动拆分时分秒做减法 - 缺少倒计时结束的判断逻辑,无法触发
isValid的状态修改
修复后完整代码
import { useState, useEffect } from 'react'; import dayjs from 'dayjs'; // 假设setIsValid是你传入的状态修改函数,可从props/上下文等位置获取 const CountdownTimer = ({ setIsValid }) => { const [minutes, setMinutes] = useState(0); const [seconds, setSeconds] = useState(0); const tokenTTL = 10; // 倒计时总时长,单位:分钟 useEffect(() => { // 仅在组件挂载时计算一次目标时间,避免时间漂移 const targetTime = dayjs().add(tokenTTL, 'minute'); const interval = setInterval(() => { const currentTime = dayjs(); // 计算当前时间和目标时间的差值,单位:毫秒 const diffMs = targetTime.diff(currentTime); // 差值小于等于0说明倒计时结束 if (diffMs <= 0) { clearInterval(interval); setMinutes(0); setSeconds(0); setIsValid(false); return; } // 将差值转换为剩余的分、秒 const remainMin = Math.floor(diffMs / 1000 / 60); const remainSec = Math.floor((diffMs / 1000) % 60); setMinutes(remainMin); setSeconds(remainSec); }, 1000); // 组件卸载时清除定时器,避免内存泄漏 return () => clearInterval(interval); }, [setIsValid]); // 补0格式化,保证展示为两位数字 const formatTimeNum = (num) => num < 10 ? `0${num}` : num; return ( <p className="Timer"> <span className="minutes">{formatTimeNum(minutes)}</span> <span className="divider">:</span> <span className="seconds">{formatTimeNum(seconds)}</span> </p> ); }; export default CountdownTimer;
逻辑说明
- 目标时间仅在组件首次挂载时计算,保证倒计时总时长固定为10分钟
- 用Day.js原生的
diff方法计算时间差,避免手动计算出现的时区、进位误差 - 每次定时器触发优先判断倒计时是否结束,符合条件立即终止定时器并修改
isValid状态 - 增加补0格式化逻辑,符合通用计时器的展示规范
内容的提问来源于stack exchange,提问作者shivetay
相关产品推荐
相关产品推荐

