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 = async () => {
const file = // synchronous code to generate a File object
return file;
}
useEffect(async () => {
if (myAction) {
setLoadingStatus('Do the thing...')
const result = await longRunningCode()
// ...
setLoadingStatus(undefined)
setMyAction(undefined)
}
}, [myAction])
//...
return <p>{loadingStatus}</p><button onClick={() => setMyAction({})} />
CodePudding user response:
I was thinking something along the lines of:
const [loadingStatus, setLoadingStatus] = useState(undefined);
const [myAction, setMyAction] = useState(undefined);
const longRunningCode = () => {
return new Promise(resolve, reject)=>{
const file = // synchronous code to generate a File object
resolve(file);
}
}
useEffect(() => {
if (myAction) {
setLoadingStatus('Do the thing...')
longRunningCode().then(file=>{
// ...
setLoadingStatus(undefined)
setMyAction(undefined)
})
}
}, [myAction])
//...
return <p>{loadingStatus}</p><button onClick={() => setMyAction({})} />
CodePudding user response:
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.