React JS - 使用 Moment.js 的倒数计时器

React JS - Countdown timer using Moment.js

我是 React 的新手 - 请耐心等待我的菜鸟问题。但是我有一个组件要在按钮内显示。我已经在 fiddle 中测试了这个功能并且它工作得很好,但是由于某种原因这个模块在我测试它时显示为空白。

(使用 moment.js)

这是我的文件:

//countdown.js
import moment from 'moment';

const CountDownTimer = () => {
    var eventTime = '1626573600';
    var currentTime = (Math.floor(Date.now() / 1000)).toString();
    var leftTime = eventTime - currentTime;
    var duration = moment.duration(leftTime, 'seconds');
    var interval = 1000;

    function ShowTimer() {
        setInterval(function(){
            // Time Out check
            if (duration.asSeconds() <= 0) {
                clearInterval(interval);
                //window.location.reload(true); //#skip the cache and reload the page from the server
            }

            //Otherwise
            duration = moment.duration(duration.asSeconds() - 1, 'seconds');
            return (duration.days() + ' Days ' + duration.hours()+ ' Hours ' + duration.minutes()+ ' Minutes ' + duration.seconds() + ' Seconds');
        }, interval);
    }

    return (
        <span>{ShowTimer()}</span>
    )
}
export default CountDownTimer;

用法如下:

//Slider.jsx
import React, { useState } from "react";
import CountDownTimer from "../../scripts/countdown.js";

...
...
...


   <div className="div-buyNowBtn">            
      <button id="buyNowBtn" className="white-fill-bg btn-outline btn-lg">
         Sale Active in: <CountDownTimer/>
      </button>
   </div>
            

感谢@DerekPollard,我能够执行以下操作并解决了问题。现在一切正常。

import moment from 'moment';
import { useEffect, useState } from "react";


const CountDownTimer = () => {
    

    const calculateTimeLeft = () => {
        let eventTime = '1626573600';
        let currentTime = (Math.floor(Date.now() / 1000)).toString();
        let leftTime = eventTime - currentTime;
        let duration = moment.duration(leftTime, 'seconds');
        let interval = 1000;
        if (duration.asSeconds() <= 0) {
            clearInterval(interval);
            //window.location.reload(true); //#skip the cache and reload the page from the server
        }
        duration = moment.duration(duration.asSeconds() - 1, 'seconds');
        return (duration.days() + ' Days ' + duration.hours()+ ' Hours ' + duration.minutes()+ ' Minutes ' + duration.seconds() + ' Seconds');
    }

    const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());

    useEffect(() => {
        setTimeout(() => {
            setTimeLeft(calculateTimeLeft());
        },1000);
    });
   

    return (
        <span>{timeLeft}</span>
    )
}
export default CountDownTimer;

问题

原始代码的问题是 ShowTimer 没有 return,本质上意味着您的 return 值是“void”

解决方案

我决定稍微清理一下函数并使其性能更高。为了避免由于未跟踪的内部函数 (ShowTimer) 而发生不必要的渲染,我决定提取保持不变的组件外部的逻辑 (calculateDuration)。

然后,使用 useEffect,我启动了我的计时器并确保更新一个名为 duration 的新状态变量。

最后,为了确保我们正确更新,并在组件卸载/或事件时间更改时终止计时器,我确保 clearInterval。这应该可以防止发生任何内存泄漏。

都用漂亮的蝴蝶结包裹着:

const { useCallback, useEffect, useRef, useState } = React;

const calculateDuration = eventTime => moment.duration(Math.max(eventTime - (Math.floor(Date.now() / 1000)), 0), 'seconds');

function Countdown({ eventTime, interval }) {
  const [duration, setDuration] = useState(calculateDuration(eventTime));
  const timerRef = useRef(0);
  const timerCallback = useCallback(() => {
    setDuration(calculateDuration(eventTime));
  }, [eventTime])

  useEffect(() => {
    timerRef.current = setInterval(timerCallback, interval);

    return () => {
      clearInterval(timerRef.current);
    }
  }, [eventTime]);

  return (
    <div>
      {duration.days()} Days {duration.hours()} Hours {duration.minutes()} Minutes {duration.seconds()} Seconds
    </div>
  )
}


ReactDOM.render(
  <Countdown eventTime={1626573600} interval={1000} />,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<div id="app"></div>

希望对您有所帮助!