I want to make a progress bar which increase it's value in every 5 seconds. I used setInterval which increase the state value and trying to clearInterval once state value is 100. But it's not clearing the interval and state value is not getting changed properly
import {useState, useEffect} from 'react';
function App() {
const [percentage,setPercentage] = useState(99)
let progressInterval = setInterval(()=>{
console.log(percentage);
setPercentage(percentage 1);
},10000);
// useEffect(()=> {
// },[])
useEffect(() => {
if(percentage === 100) {
console.log("completed");
clearInterval(progressInterval);
}
}, [percentage])
const progress = {
backgroundColor: 'yellow',
width: `${percentage}%`,
textAlign: 'right',
}
const fullWidth = {
border: '1px solid black',
backgroundColor: '#eff',
margin: '10px'
}
return (
<>
<div style={fullWidth}>
<div style={progress}>{percentage}%</div>
</div>
</>
);
}
export default App;
CodePudding user response:
When you change the state your component will be rerender and your progressInterval
variable will be reinitialize.
you should initizalize the variable of interval inside a callback function:
import {useState, useEffect, useCallback} from 'react';
let progressInterval = '';
function App() {
const [percentage,setPercentage] = useState(99);
const initInterval = useCallback(() => {
progressInterval = setInterval(()=>{
console.log(percentage);
setPercentage(percentage 1);
},10000);
}, []);
useEffect(() => {
if(percentage === 100) {
console.log("completed");
clearInterval(progressInterval);
}
}, [percentage])
const progress = {
backgroundColor: 'yellow',
width: `${percentage}%`,
textAlign: 'right',
}
const fullWidth = {
border: '1px solid black',
backgroundColor: '#eff',
margin: '10px'
}
return (
<>
<div style={fullWidth}>
<div style={progress}>{percentage}%</div>
</div>
</>
);
}
export default App;
CodePudding user response:
If progressInterval
can be a state variable, this might be the solution:
function App() {
const [percentage, setPercentage] = useState(99);
const [progressInterval, setProgressInterval] = useState();
useEffect(() => {
let progressInterval = setInterval(() => {
console.log(percentage);
setPercentage((prev) => prev 1);
}, 10000);
setProgressInterval(progressInterval);
// Optional but a recommendation
// Clearing the interval if component unmounts before reaching 100 percent
return () => clearInterval(progressInterval);
}, []);
useEffect(() => {
if (percentage === 100) {
console.log("completed");
clearInterval(progressInterval);
}
}, [percentage]);
... rest of the code
}
CodePudding user response:
You can set a return function to your useEffect like this
useEffect(() => {
const timer = setTimeout(() => {
if(progress < 0.9){
setProgress(progress 0.2);
}
else{
retrieveData();
}
}, 1000);
return () => {
clearTimeout(timer);
};
}, [progress]);