I'm very new to React - so bear with my noob question. But I have a component I'm trying to display inside a button. I've tested the function in a fiddle and it works great, but for some reason this module is showing up blank when I test it.
(using moment.js)
Here's my files:
//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;
Here's the usage:
//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>
The issue with the original code is that ShowTimer
was returning nothing, essentially meaning your return value was "void"
I decided to clean up the function a bit and make it more performant. Instead of having unnecessary renders occur due to un-tracked internal functions (ShowTimer
) I decided to extract the logic outside of the component that stayed constant (calculateDuration
).
Then, using useEffect
, I started my timer and made sure to update a new state variable called duration
.
Finally, to ensure we properly update, and kill the timer whenever the component unmounts / or the event time changes, I make sure to clearInterval. This should prevent any memory leaks from occurring.
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>
Hope this helped!