packages/bui-core/src/Countdown/useCountdown.ts (40 lines of code) (raw):

import { useEffect, useMemo, useState } from 'react'; import { CurrentTime } from './Countdown.types'; import { parseTime } from './utils'; const REFRESH_INTERVAL = 50; export default ({ startTime: startTimestamp, endTime: endTimestamp, onChange, }) => { // 初始化时间差 const initOffsetTime = useMemo( () => startTimestamp - new Date().getTime(), [startTimestamp, endTimestamp], ); const [time, setTime] = useState<CurrentTime>( parseTime(endTimestamp, initOffsetTime), ); const [isEnd, setIsEnd] = useState(false); useEffect(() => { setIsEnd(false); if ( startTimestamp === 0 || endTimestamp === 0 || endTimestamp <= startTimestamp ) { return; } // 重新计算时间差 const offsetTime = startTimestamp - new Date().getTime(); const timer = setInterval(() => { const currentTime = parseTime(endTimestamp, offsetTime); setTime(currentTime); onChange?.({ value: currentTime }); if (currentTime.total <= 0 || !endTimestamp) { setIsEnd(true); clearInterval(timer); } }, REFRESH_INTERVAL); // eslint-disable-next-line consistent-return return () => clearInterval(timer); }, [startTimestamp, endTimestamp]); return { time, isEnd }; };