Setinterval In A React App
Solution 1:
I see 4 issues with your code:
- In your timer method you are always setting your current count to 10
- You try to update the state in render method
- You do not use
setState
method to actually change the state - You are not storing your intervalId in the state
Let's try to fix that:
componentDidMount: function() {
var intervalId = setInterval(this.timer, 1000);
// store intervalId in the state so it can be accessed later:this.setState({intervalId: intervalId});
},
componentWillUnmount: function() {
// use intervalId from the state to clear the intervalclearInterval(this.state.intervalId);
},
timer: function() {
// setState method is used to update the statethis.setState({ currentCount: this.state.currentCount -1 });
},
render: function() {
// You do not need to decrease the value herereturn (
<section>
{this.state.currentCount}
</section>
);
}
This would result in a timer that decreases from 10 to -N. If you want timer that decreases to 0, you can use slightly modified version:
timer: function() {
var newCount = this.state.currentCount - 1;
if(newCount >= 0) {
this.setState({ currentCount: newCount });
} else {
clearInterval(this.state.intervalId);
}
},
Solution 2:
Updated 10-second countdown using class Clock extends Component
importReact, { Component } from'react';
classClockextendsComponent {
constructor(props){
super(props);
this.state = {currentCount: 10}
}
timer() {
this.setState({
currentCount: this.state.currentCount - 1
})
if(this.state.currentCount < 1) {
clearInterval(this.intervalId);
}
}
componentDidMount() {
this.intervalId = setInterval(this.timer.bind(this), 1000);
}
componentWillUnmount(){
clearInterval(this.intervalId);
}
render() {
return(
<div>{this.state.currentCount}</div>
);
}
}
module.exports = Clock;
Solution 3:
Updated 10-second countdown using Hooks (a new feature proposal that lets you use state and other React features without writing a class. They’re currently in React v16.7.0-alpha).
importReact, { useState, useEffect } from'react';
importReactDOM from'react-dom';
constClock = () => {
const [currentCount, setCount] = useState(10);
consttimer = () => setCount(currentCount - 1);
useEffect(
() => {
if (currentCount <= 0) {
return;
}
const id = setInterval(timer, 1000);
return() =>clearInterval(id);
},
[currentCount]
);
return<div>{currentCount}</div>;
};
constApp = () => <Clock />;
ReactDOM.render(<App />, document.getElementById('root'));
Solution 4:
If anyone is looking for a React Hook approach to implementing setInterval. Dan Abramov talked about it on his blog. Check it out if you want a good read about the subject including a Class approach. Basically the code is a custom Hook that turns setInterval as declarative.
functionuseInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.useEffect(() => {
functiontick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return() =>clearInterval(id);
}
}, [delay]);
}
Also posting the CodeSandbox link for convenience: https://codesandbox.io/s/105x531vkq
Solution 5:
Manage setInterval with React Hooks:
const [seconds, setSeconds] = useState(0)
const interval = useRef(null)
useEffect(() => { if (seconds === 60) stopCounter() }, [seconds])
conststartCounter = () => interval.current = setInterval(() => {
setSeconds(prevState => prevState + 1)
}, 1000)
conststopCounter = () => clearInterval(interval.current)
Post a Comment for "Setinterval In A React App"