前端手撕题—倒计时组件

#一人分享一道面试手撕题#
得物、拼多多经常考,倒计时组件

1.倒计时组件
2.如何实现精确计时(setInterval 1s先就update以前知道写但没考虑到为什么,时间戳同步)

// Countdown.jsx
import React, { useEffect, useState, useRef } from 'react';

/**
 * props:
 *  - endAt: number (timestamp ms) 或 Date
 *  - onFinish?: () => void
 *  - tickMs?: number (minimal tick granularity, default 1000)
 */
export default function Countdown({ endAt, onFinish, tickMs = 1000 }) {
  const endTs = typeof endAt === 'number' ? endAt : endAt.getTime();
  const [remaining, setRemaining] = useState(Math.max(0, endTs - Date.now()));
  const mounted = useRef(true);

  useEffect(() => {
    mounted.current = true;
    // initial sync
    function update() {
      const now = Date.now();
      const rem = Math.max(0, endTs - now);
      if (!mounted.current) return;
      setRemaining(rem);
      if (rem === 0) {
        onFinish?.();
        return;
      }
      // Align next update to wall-clock second boundary (or tickMs)
      const delay = Math.min(
        tickMs,
        1000 - (now % 1000) // align to next second for nicer UX
      );
      // If <1s left, use requestAnimationFrame for smoothness
      if (rem <= 1000) {
        requestAnimationFrame(update);
      } else {
        setTimeout(update, delay);
      }
    }

    update();
    return () => {
      mounted.current = false;
    };
  }, [endTs, onFinish, tickMs]);

  const sec = Math.ceil(remaining / 1000);
  const mm = Math.floor(sec / 60);
  const ss = sec % 60;
  return (
    <div>
      {mm}:{String(ss).padStart(2, '0')}
    </div>
  );
}

全部评论

相关推荐

点赞 评论 收藏
分享
评论
1
10
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务