要求可以每秒自动更新并返回当前剩余时间,其返回值满足以下定义:
// 返回值定义
interface Countdown {
expired: boolean; // 是否已到期
days: number; // 剩余天数(整数),最小为0
hours: number; // 剩余小时数(整数),最大为 23,最小为0
minutes: number; // 剩余分钟数(整数),最大为 59,最小为0
seconds: number; // 剩余秒数(整数),最大为 59,最小为0
}
Notice:
若剩余时间为0,则停止计时
应用程序在压后台时为优化性能,页面容器的tick会变慢(setInterval 1s,可能实际2s以上才会触发一次),基于该情况,请考虑如何准确计时
import { useEffect, useState } from 'react'; import moment from 'moment'; // 入参 export interface ICountdown { deadline: string; format?: 'YYYY-MM-DD HH:mm:ss' | string; } // 返回值 export type Remains = Record<'day' | 'hour' | 'minute' | 'second', number>; const useCountdown = ({ deadline, format = 'YYYY-MM-DD HH:mm:ss', }: ICountdown): Remains => { // 由于 moment() 返回对象,setCurrent 修改值后指针不变,无法在 useEffect 中捕获变化,所以这里定义了一个 updater 用于 useEffect 捕获时间更新 const [{ current, updater }, setCurrent] = useState({ current: moment(), updater: 0, }); const [remains, setRemains] = useState<Remains>({ day: 0, hour: 0, minute: 0, second: 0, }); useEffect(() => { const timer = window.setInterval(() => { current.isSameOrAfter(moment(deadline, format)) ? clearInterval(timer) : setCurrent(prev => ({ current: prev.current.add(1, 's'), updater: prev.updater + 1, })); }, 1000); return () => clearInterval(timer); }, [deadline]); // current 变化,计算相差多长时间 useEffect(() => { let millisec = moment(deadline, format).valueOf() - current.valueOf(); // 处理 millisec 可能为负数的情况 millisec = millisec >= 0 ? millisec : 0; // 用毫秒数得到秒、分、小时和天 setRemains({ day: Math.floor(millisec / (1000 * 60 * 60 * 24)), hour: Math.floor((millisec / (1000 * 60 * 60)) % 24), minute: Math.floor((millisec / (1000 * 60)) % 60), second: Math.round((millisec / 1000) % 60), }); }, [updater]); return remains; }; export default useCountdown;
// countdown import React, { useMemo } from 'react'; import useCountdown from '@/components/Countdown'; import moment from 'moment'; const Index = () => { const deadline = useMemo( () => moment() .add(4, 's') .add(1, 'm') .add(1, 'h') .add(1, 'd') .format('YYYY-MM-DD HH:mm:ss'), [], ); const { day, hour, minute, second } = useCountdown({ // deadline: '2021-04-22 17:49:00', deadline, }); return <h1>{`${day}天${hour}时${minute}分${second}秒`}</h1>; }; export default Index;
标签:current,const,hooks,60,倒计时,moment,deadline,组件,millisec From: https://www.cnblogs.com/judyhuayu/p/16994533.html