I have a progress bar the value should be from 0.1 to 1.
but sometimes progressValue
will over 1, for example refresh the page.
Why ?
https://codesandbox.io/p/devbox/g9wwqf?file=%2Fsrc%2FApp.jsx%3A6%2C1
import "./styles.css";
import axios from "axios";
import { useState, useEffect } from "react";
let intervalId;
export default function App() {
const [progressValue, setProgressValue] = useState(0);
useEffect(() => {
intervalId = setInterval(() => {
if (progressValue < 1) {
setProgressValue((t) => t + 0.3);
}
}, 100);
return () => clearInterval(intervalId);
}, []);
useEffect(() => {
axios
.get("https://randomuser.me/api/?results=5")
.then((value) => {
// success
clearInterval(intervalId);
setProgressValue(1);
})
.catch((error) => {
// error
clearInterval(intervalId);
setProgressValue(1);
});
}, []);
console.log("progressValue =>", progressValue);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
2
Answers
Please pass the
progressValue
dependency correctly to the effect. Otherwise theprogressValue
will always refer to the value ofprogressValue
from the very first render, which was0
.If you log the value of
progressValue
before the if condition, it will log0
. That’s just how closures work. So anyway doing that condition check will do you no good.Instead you can make use of the condition inside the setState callback correctly like:
I am sure you are looking for the sum value to not exceed 1, so the conditions should check for that and not
t < 1
You should make your
intervalId
a part of yourApp
component. A way to achieve this would be to create a reference usinguseRef
.I also wrapped the Axios call in a 1 second delay so that the progress effect can actually be seen.