I’m currently using a simple Countdown Timer component. This is the code of the component:
import React, { useState, useRef, useEffect, useCallback } from 'react' const Timer = ({time}) => { // We need ref in this, because we are dealing // with JS setInterval to keep track of it and // stop it when needed const Ref = useRef(null); // The state for our timer const [timer, setTimer] = useState('00:00:00'); const number = 1000 const getTimeRemaining = (e) => { var total = (Date.parse(e) - Date.parse(new Date())) / 1000; // calculate (and subtract) whole days var days = Math.floor(total / 86400); total -= days * 86400; // calculate (and subtract) whole hours var hours = Math.floor(total / 3600) % 24; total -= hours * 3600; // calculate (and subtract) whole minutes var minutes = Math.floor(total / 60) % 60; total -= minutes * 60; // what's left is seconds var seconds = total % 60; return { total, days, hours, minutes, seconds }; } const startTimer = (e) => { let { total, days, hours, minutes, seconds } = getTimeRemaining(e); if (total >= 0) { // update the timer // check if less than 10 then we need to // add '0' at the beginning of the variable setTimer( (days < 1 ? '00' : days) + ':' + (hours > 9 ? hours : '0' + hours) + ':' + (minutes > 9 ? minutes : '0' + minutes) + ':' + (seconds > 9 ? seconds : '0' + seconds) ) } } const clearTimer = (e) => { // If you adjust it you should also need to // adjust the Endtime formula we are about // to code next setTimer('00:00:10'); // If you try to remove this line the // updating of timer Variable will be // after 1000ms or 1sec if (Ref.current) clearInterval(Ref.current); const id = setInterval(() => { startTimer(e); }, 1000) Ref.current = id; } const getDeadTime = () => { let deadline = new Date(); // This is where you need to adjust if // you entend to add more time deadline.setSeconds(deadline.getSeconds() + Math.floor(time)); return deadline; } // We can use useEffect so that when the component // mount the timer will start as soon as possible // We put empty array to act as componentDid // mount only useEffect(() => { clearTimer(getDeadTime()); }, []); // Another way to call the clearTimer() to start // the countdown is via action event from the // button first we create function to be called // by the button return ( <div className="App"> <h2 className='text-3xl lg:text-4xl text-transparent bg-clip-text text-center bg-gradient-to-r from-pink-500 via-red-500 to-yellow-500'>{timer}</h2> </div> ) } export default Timer;
My issue is that everytime I refresh my page, the timer starts again. I understand this has something to do with react re-rendering the components and I need to move this to a higher level to save state, but I’m not sure exactly how to do that.
Also, I use the time as a sort of prop, where everytime a user creates a new listing on my website, a new timer starts for that particular listing.
So how exactly can I make my timer save state for already created listings, while at the same time allowing it to create new listings?
Thanks!
Advertisement
Answer
First of all, I’m not sure what do you mean by “refresh page”, if you mean that you hit ctrl+r and reload browser tab, the you restart your application entirely and it’s not about react state. In this case you need to store somewhere your current state and update your local state from that data after refresh.
So you need to save your timer start time in local storage or on server side so you would have an ability to initialize your timer using that time and it will continue running after page reload