I have a long process that updates the state. I want to show red background when it's running and blue when it's done.
const MapBuilder = (props) => {
const [backgroundColor, setBackgroundColor] = useState(false);
const [fancyResult, setFancyResult] = useState(null);
console.log(`stop 1 backgroundColor ${backgroundColor} fancyResult ${fancyResult}`)
const veryHardWork = () => {
setBackgroundColor("red");
console.log(`stop 2 backgroundColor ${backgroundColor} fancyResult ${fancyResult}`)
for (let i = 0; i < 1000; i++) {
for (let j = 0; j < 1000; j++) {
console.log("So hard")
}
}
setFancyResult("done")
console.log(`stop 3 backgroundColor ${backgroundColor} fancyResult ${fancyResult}`)
setBackgroundColor("blue")
console.log(`stop 4 backgroundColor ${backgroundColor} fancyResult ${fancyResult}`)
}
return (<div style={{background: backgroundColor}}>
<button className="btn btn-primary" onClick={veryHardWork}></button>
</div>)
}
Here is an output of such run
stop 1 backgroundColor false fancyResult null
MapBuilder.js:13 stop 2 backgroundColor false fancyResult null
10000MapBuilder.js:16 So hard
MapBuilder.js:20 stop 3 backgroundColor false fancyResult null
MapBuilder.js:22 stop 4 backgroundColor false fancyResult null
MapBuilder.js:10 stop 1 backgroundColor blue fancyResult done
I understand from this that the state change only happens after the method veryHardWork
is finished. In my real project, I actually want to show a spinner the question is how can I do it if the state is only changed at the end of the method.
I think some clarification needs to be added. In reality, I allow the user to choose a file after the user chooses the file it is loaded and some heavy processing is performed on files data while the processing is running I want to show a spinner no Asyn work involved.
Some of the answers sugested to use useEffect and moving it to a promise I tryied both but it did not help here is a different take on it which also did not work
const MapBuilder = (props) => {
const [backgroundColor, setBackgroundColor] = useState(false);
const [fancyResult, setFancyResult] = useState(null);
const [startProcessing, setStartProcessing] = useState(null);
useEffect(() => {
let myFunc = async () => {
if (startProcessing) {
setBackgroundColor("red");
await hardWork();
setBackgroundColor("blue");
setStartProcessing(false);
}
}
myFunc();
}, [startProcessing])
const hardWork = () => {
return new Promise((resolve)=> {
for (let i = 0; i < 500; i++) {
for (let j = 0; j < 100; j++) {
console.log("So hard")
}
}
setFancyResult("sdsadsad")
resolve("dfsdfds")
})
}
return (<div style={{background: backgroundColor}}>
<button className="btn btn-primary" onClick={() => setStartProcessing(true)}></button>
</div>)
}
export default MapBuilder;