I am new to React and I try to build a timer ponent. Now I have the start function working but I would also like to stop the timer by an onclick handler. The problem is that the start function uses an interval, but I don't know how to stop that interval from another function.
My JS code
constructor() {
super();
this.state = {
times: [],
timer: false,
currentTimer: 0
}
this.startTimer = this.startTimer.bind(this);
this.stopTimer = this.stopTimer.bind(this);
}
startTimer() {
const start = Date.now();
this.setState({ timer: true });
var timer = setInterval(() => {
let time = new Date() - start;
this.setState({ currentTimer: Math.round(time / 1000)});
}, 1000);
}
stopTimer() {
this.setState({ timer: false });
console.log('stopped');
//Clear interval here
}
I know that the timer
variable is the identifier of that interval but how can I access it and then stop it? I have tried almost everything but nothing seems to work and I just don't know how I can fix that.
I am new to React and I try to build a timer ponent. Now I have the start function working but I would also like to stop the timer by an onclick handler. The problem is that the start function uses an interval, but I don't know how to stop that interval from another function.
My JS code
constructor() {
super();
this.state = {
times: [],
timer: false,
currentTimer: 0
}
this.startTimer = this.startTimer.bind(this);
this.stopTimer = this.stopTimer.bind(this);
}
startTimer() {
const start = Date.now();
this.setState({ timer: true });
var timer = setInterval(() => {
let time = new Date() - start;
this.setState({ currentTimer: Math.round(time / 1000)});
}, 1000);
}
stopTimer() {
this.setState({ timer: false });
console.log('stopped');
//Clear interval here
}
I know that the timer
variable is the identifier of that interval but how can I access it and then stop it? I have tried almost everything but nothing seems to work and I just don't know how I can fix that.
4 Answers
Reset to default 5To stop the timer, you need the timer id, So First job will be to store the id in such a way that it should be accessible in all the class methods.
Second job will be use clearInterval
to clear the timer (timer id will be required here).
One option is, Store the timer id in class instance.
Like this:
startTimer() {
const start = Date.now();
this.setState({ timer: true });
// storing the id
this.timerID = setInterval(() => {
let time = new Date() - start;
this.setState({ currentTimer: Math.round(time / 1000)});
}, 1000);
}
stopTimer() {
this.setState({ timer: false });
clearInterval(this.timerID);
}
Working code:
class App extends React.Component {
constructor(){
super();
this.state = {currentTimer: ''}
this.startTimer = this.startTimer.bind(this);
this.stopTimer = this.stopTimer.bind(this);
}
startTimer() {
const start = Date.now();
this.timerID = setInterval(() => {
let time = Math.random() * 10;
this.setState({ currentTimer: time});
}, 1000);
}
stopTimer() {
clearInterval(this.timerID);
}
render(){
return (
<div>
Value: {this.state.currentTimer || '0'}
<br />
<button onClick={this.startTimer}>Start timer</button>
<button onClick={this.stopTimer}>Stop timer</button>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app' />
Save the timerId as a class instance variable which can then be accessed from other functions and used to clear the interval
constructor() {
super();
this.state = {
times: [],
timer: false,
currentTimer: 0
}
this.timer = null;
this.startTimer = this.startTimer.bind(this);
this.stopTimer = this.stopTimer.bind(this);
}
startTimer() {
const start = Date.now();
this.setState({ timer: true });
this.timer = setInterval(() => {
let time = new Date() - start;
this.setState({ currentTimer: Math.round(time / 1000)});
}, 1000);
}
stopTimer() {
this.setState({ timer: false });
console.log('stopped');
//Clear interval here
clearInterval(this.timer)
}
Your timer
variable is a local variable to startTimer()
method, it stores the identifier of that interval but is not accessible outside the function scope.
To fix this, add following in constructor()
method:
this.timer = null;
Then, in startTimer()
method change:
var timer = setInterval(() => {
let time = new Date() - start;
this.setState({ currentTimer: Math.round(time / 1000)});
}, 1000);
to:
this.timer = setInterval(() => {
let time = new Date() - start;
this.setState({ currentTimer: Math.round(time / 1000)});
}, 1000);
Finally, add following in stopTimer()
method:
//Clear interval here code here
clearInterval(this.timer);
Not sure if it`s the right approach, but if you look for a quick workaround, just make it global(outside Component). It works, soooo....)
Edit : in Functional Components you have to use useRef()
link to ReactDOC: https://reactjs/docs/hooks-faq.html#is-there-something-like-instance-variables