Home > front end >  In React useEffect, how do you sneak state updates in between long running code?
In React useEffect, how do you sneak state updates in between long running code?

Time:02-03

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.

  •  Tags:  
  • Related