背景:
实际工作中遇到这么一个需求,后端只给了截止时间,要来个实时倒计时的展示;刚拿到这个需求时,惯性思维,写一个函数 就好了;结果试了半天不行,最后查阅,获得启发,还是需要封装一个组件的;
import * as React from 'react';
import styles from './index.less';
const { useState, useEffect, useRef } = React;
interface IProps {
timeStamp: any;
}
/**
* 组件:倒计时组件
* @param props:传入的时间戳是,以秒单位的,不是毫秒
* @returns
*/
const CountDown = (props: IProps) => {
const { timeStamp } = props;
const intervalRef = useRef<any>(null);
const now: any = Math.round(new Date().getTime() / 1000).toString(); // 获取当前时间
const end: any = timeStamp; // 设置截止时间
const [leftTime, setLeftTime] = useState(end - now); // 时间间隔
const [day, setDay] = useState<any>(''); // 天
const [h, setHours] = useState<any>(''); // 小时
const [m, setMinutes] = useState<any>(''); // 分钟
const [s, setSeconds] = useState<any>(''); // 秒
useEffect(() => {
if (leftTime > 0) {
intervalRef.current = setInterval(() => {
const newNow: any = Math.round(new Date().getTime() / 1000).toString(); // 重新获取当前时间
const newLeftTime = timeStamp - newNow;
setLeftTime(() => newLeftTime); // 计算新的时间间隔数值
const tempDay = Math.floor((newLeftTime / 60 / 60 / 24) % 24);
const hours = Math.floor((newLeftTime / 60 / 60) % 24) < 10 ? `0${Math.floor((newLeftTime / 60 / 60) % 24)}` : Math.floor((newLeftTime / 60 / 60) % 24);
const minutes = Math.floor((newLeftTime / 60) % 60) < 10 ? `0${Math.floor((newLeftTime / 60) % 60)}` : Math.floor((newLeftTime / 60) % 60);
const seconds = Math.floor(newLeftTime % 60) < 10 ? `0${Math.floor(newLeftTime % 60)}` : Math.floor(newLeftTime % 60);
setDay(() => tempDay);
setHours(() => hours); // 函数写法 设置小时
setMinutes(() => minutes); // 函数写法 设置分钟
setSeconds(() => seconds); // 函数写法保证值在setInterval里更新,避免useEffect的bug
}, 1000);
} else {
setLeftTime(0);
setDay(0);
setHours(0);
setMinutes(0);
setSeconds(0);
clearInterval(intervalRef.current);
}
return () => clearInterval(intervalRef.current);
}, []); // 不传依赖
return (
<>
{leftTime <= 0 && (
<span className={styles.timeWrap}>
<span>{0}</span>天<span>{0}</span>小时
<span>{0}</span>分
</span>
)}
{leftTime > 0 && (
<span className={styles.timeWrap}>
<span>{day}</span>天<span>{h}</span>小时
<span>{m}</span>分
</span>
)}
</>
);
};
export default CountDown;