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>
希望对您有所帮助!
我是 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>
希望对您有所帮助!