'In React useEffect, how do you sneak state updates in between long running code?
I'm having trouble getting my loading status to appear before the longRunningCode executes. I tried making it async to no avail.
const [loadingStatus, setLoadingStatus] = useState(undefined);
const [myAction, setMyAction] = useState(undefined);
const longRunningCode = () => {
const file = // synchronous code to generate a gzipped File object
return file;
}
// also tried
// const longRunningCode = async () => {
// ...
useEffect(() => {
if (myAction) {
setLoadingStatus('Do the thing...')
const result = longRunningCode()
// also tried `await` with async version
// ...
setLoadingStatus(undefined)
setMyAction(undefined)
}
}, [myAction])
//...
return (
<div>
<p>{loadingStatus}</p>
<button onClick={() => setMyAction({})}>Generate file</button>
</div>
)
Solution 1:[1]
useEffect callbacks are only allowed to return undefined or a destructor function. In your example, you have passed an async function which returns a Promise. It may or may not run, but you will see React warnings that useEffect callbacks are run synchronously.
Instead, define an async function, and then call it.
const [loadingStatus, setLoadingStatus] = useState(undefined);
const [myAction, setMyAction] = useState(undefined);
useEffect(() => {
const doAction = async () => {
if (myAction) {
setLoadingStatus('Do the thing...');
const result = await longRunningCode();
// ...
setLoadingStatus(undefined);
setMyAction(undefined);
}
};
doAction();
}, [myAction]);
//...
return <p>{loadingStatus}</p><button onClick={() => setMyAction({})} />
Otherwise, what you have written will work.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Benjamin |
