I have a React App that counts years, days, hours, minutes and second from a given date.
Timer.js
function Timer() {
const startDate = new Date(2000, 0, 0, 0, 0, 0, 0);
var now = new Date();
var diff = now.getTime() - startDate.getTime();
var years = Math.floor((diff / (1000 * 60 * 60 * 24 * 365)));
diff = diff % (1000 * 60 * 60 * 24 * 365);
var days = Math.floor((diff / (1000 * 60 * 60 * 24)));
diff = diff % (1000 * 60 * 60 * 24);
var hrs = Math.floor((diff / (1000 * 60 * 60)));
diff = diff % (1000 * 60 * 60);
var min = Math.floor((diff / (1000 * 60)));
diff = diff % (1000 * 60);
var sec = now.getSeconds(Math.floor((diff / (1000))));
diff = diff % (1000);
return (<div>
{years} years,
<br /> {days} days,
<br /> {hrs} hours,
<br /> {min} minutes,
<br /> {sec} seconds
</div>);
}
export default Timer;
App.js
import Timer from './Timer';
function App() {
return (
<div>
<div>
<Timer />
</div>
</div>
);
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
reportWebVitals();
I get an output like this:
22 years,
209 days,
50 minutes,
19 hours,
13 seconds
I want it to be updated every second without reloading the page. I tried with
setTimeout(timer, 1000);
in the Timer function but it didn't work.
What do I need?
CodePudding user response:
You just need to save the now
object as a state variable and update it within useEffect hook, using setTimeout.
Update: Much more clear version of the code:
function Timer() {
const [nowMs, setNowMs] = useState(Date.now());
const startDateMs = useMemo(() => {
return new Date(2000, 0, 0, 0, 0, 0, 0).getTime();
}, []);
const { years, days, hrs, min, sec } = useMemo(() => {
let diff = nowMs - startDateMs;
const years = Math.floor(diff / (1000 * 60 * 60 * 24 * 365));
diff = diff % (1000 * 60 * 60 * 24 * 365);
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
diff = diff % (1000 * 60 * 60 * 24);
const hrs = Math.floor(diff / (1000 * 60 * 60));
diff = diff % (1000 * 60 * 60);
const min = Math.floor(diff / (1000 * 60));
diff = diff % (1000 * 60);
const sec = Math.floor(diff / 1000);
diff = diff % 1000;
return { years, days, hrs, min, sec };
}, [nowMs, startDateMs]);
useEffect(() => {
const intervalId = setInterval(() => {
setNowMs(Date.now());
}, 1000);
return () => clearInterval(intervalId);
}, []);
return (
<div>
{years} years,
<br /> {days} days,
<br /> {hrs} hours,
<br /> {min} minutes,
<br /> {sec} seconds
</div>
);
}
CodePudding user response:
you can use
[time, setTime] = useState();
useEffect(() => {
setTimeout(() => {
// do your stuff and call setTime() to rerender this component
}, 1000);
}, []);