fix: 修复延长有效期后倒计时不立即更新的问题

This commit is contained in:
gujiangjiang committed 2025-10-19 09:44:27 +08:00
1 parent 8f2244028c
commit 8147173290
1 file changed
+29 -14
+29 -14
View File
@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react'; import { useState, useEffect, useCallback } from 'react'; // fix: 导入 useCallback
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import ClockIcon from './icons/Clock'; // 导入时钟图标 import ClockIcon from './icons/Clock'; // 导入时钟图标
import RefreshIcon from './icons/RefreshIcon'; // 导入刷新图标 import RefreshIcon from './icons/RefreshIcon'; // 导入刷新图标
@@ -17,8 +17,9 @@ const formatTimeUnit = (unit: number): string => {
export function CountdownTimer({ expiryTimestamp, onExtend }: CountdownTimerProps) { export function CountdownTimer({ expiryTimestamp, onExtend }: CountdownTimerProps) {
const { t } = useTranslation(); // 用于国际化 const { t } = useTranslation(); // 用于国际化
// 计算剩余时间的函数 // 计算剩余时间的函数 (使用 useCallback 避免不必要的重新创建)
const calculateTimeLeft = () => { const calculateTimeLeft = useCallback(() => {
// 直接使用最新的 expiryTimestamp prop
const difference = expiryTimestamp - Date.now(); const difference = expiryTimestamp - Date.now();
let timeLeft = { let timeLeft = {
hours: '00', hours: '00',
@@ -28,34 +29,48 @@ export function CountdownTimer({ expiryTimestamp, onExtend }: CountdownTimerProp
}; };
if (difference > 0) { if (difference > 0) {
const totalSeconds = Math.floor(difference / 1000);
const seconds = totalSeconds % 60;
const totalMinutes = Math.floor(totalSeconds / 60);
const minutes = totalMinutes % 60;
const hours = Math.floor(totalMinutes / 60); // 不再限制 % 24,可以显示超过一天的时间
timeLeft = { timeLeft = {
hours: formatTimeUnit(Math.floor((difference / (1000 * 60 * 60)) % 24)), hours: formatTimeUnit(hours),
minutes: formatTimeUnit(Math.floor((difference / 1000 / 60) % 60)), minutes: formatTimeUnit(minutes),
seconds: formatTimeUnit(Math.floor((difference / 1000) % 60)), seconds: formatTimeUnit(seconds),
expired: false, expired: false,
}; };
} }
return timeLeft; return timeLeft;
}; }, [expiryTimestamp]); // expiryTimestamp 作为依赖项
// 使用 useState 来存储剩余时间 // 使用 useState 来存储剩余时间
const [timeLeft, setTimeLeft] = useState(calculateTimeLeft()); const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());
// 使用 useEffect 来设置定时器,每秒更新剩余时间 // 使用 useEffect 来设置定时器,每秒更新剩余时间
useEffect(() => { useEffect(() => {
// 如果已经过期,则不设置定时器 // 立即计算一次以避免初始延迟
if (timeLeft.expired) { setTimeLeft(calculateTimeLeft());
return;
}
// 设置定时器
const timer = setInterval(() => { const timer = setInterval(() => {
setTimeLeft(calculateTimeLeft()); setTimeLeft(calculateTimeLeft());
}, 1000); }, 1000);
// 组件卸载时清除定时器 // 组件卸载或 expiryTimestamp 变化时清除定时器
// fix: 将 expiryTimestamp 添加到依赖项,确保每次时间戳更新时都重置定时器
return () => clearInterval(timer); return () => clearInterval(timer);
}, [expiryTimestamp, timeLeft.expired]); // 依赖项包含过期时间戳和是否过期状态 }, [expiryTimestamp, calculateTimeLeft]); // 依赖项包含 expiryTimestamp 和 calculateTimeLeft
// 当计算出的时间显示已过期时,停止计时器(通过清除上一个 effect 实现)
useEffect(() => {
if (timeLeft.expired) {
// 定时器已在上面的 effect 的 cleanup 函数中清除
// 这里可以额外处理过期逻辑,如果需要的话
}
}, [timeLeft.expired]);
return ( return (
// feat: 将容器改为 flex-row 并添加按钮 // feat: 将容器改为 flex-row 并添加按钮
@@ -70,7 +85,7 @@ export function CountdownTimer({ expiryTimestamp, onExtend }: CountdownTimerProp
</span> // 显示剩余时间 时:分:秒 </span> // 显示剩余时间 时:分:秒
)} )}
</div> </div>
{/* feat: 添加延长有效期按钮 */} {/* feat: 添加延长有效期按钮, 仅在未过期时显示 */}
{!timeLeft.expired && ( {!timeLeft.expired && (
<button <button
onClick={onExtend} onClick={onExtend}