'How to update a clock every second in React js recursively?
I am trying to create a react app that updates every second. If I use setInterval inside the render, it may overload the task. So, I want to call the setInterval function only after the clock has finished rendering. When I tried running the code, it says that the maximum recursion depth has been exceeded. I know it's an infinite loop but since it will execute only after waiting for 1 second, is there a way to get around this? Here is the code:
import React from 'react';
export class Fluctuation extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
time: new Date(),
}
}
updateTime() {
this.setState({time: new Date()})
}
updateTimeRecursively() {
this.updateTime();
setInterval(this.updateTime(), 1000);
}
render() {
this.updateTimeRecursively();
return (
<main>
<div className="time-container">
<div className="hours">{this.state.time.getHours()}</div>:
<div className="minutes">{this.state.time.getMinutes()}</div>:
<div className="seconds">{this.state.time.getSeconds()}</div>
</div>
<button onClick={() => this.updateTime()}>Update Time</button>
</main>
)
}
}
Solution 1:[1]
Few things to correct,
- Remove calling
updateTimeRecursivelyfrom therendermethod it causes to exceed the maximum update depth. - Call it within
componentDidMountlifecycle method. setIntervalaccepts a function, not a function call.
class Fluctuation extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
time: new Date()
};
}
updateTime = () => {
this.setState({ time: new Date() });
};
updateTimeRecursively() {
this.updateTime();
setInterval(this.updateTime, 1000);
}
componentDidMount = () => {
this.updateTimeRecursively();
};
render() {
return (
<main>
<div className="time-container">
<div className="hours">{this.state.time.getHours()}</div>:
<div className="minutes">{this.state.time.getMinutes()}</div>:
<div className="seconds">{this.state.time.getSeconds()}</div>
</div>
<button onClick={() => this.updateTime()}>Update Time</button>
</main>
);
}
}
ReactDOM.render(<Fluctuation/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Solution 2:[2]
Solution for a functional component -
import React, { useEffect } from "react";
export default function App() {
const [time, setTime] = React.useState('');
useEffect(()=>{
setInterval(()=>{ let nwDate = new Date(); setTime(nwDate)}, 1000);
},[])
return (
<div className="App">
<h1>{time.toString()}</h1>
</div>
);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Amila Senadheera |
| Solution 2 |
