Tengo problemas para que aparezca mi estado de carga antes de que se ejecute longRunningCode. Intenté hacerlo asíncrono sin éxito.
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> )Estaba pensando en algo como:
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({})} />**Editar: ** con setTimeout
const [loadingStatus, setLoadingStatus] = useState(undefined); const [myAction, setMyAction] = useState(undefined); const longRunningCode = () => { const file = // synchronous code to generate a File object return file } } useEffect(() => { if (myAction) { setLoadingStatus('Do the thing...') //a 0 second delay timer waiting for longrunningcode to finish let timer = setTimeout(() =>{ longRunningCode() setLoadingStatus(undefined) setMyAction(undefined) }, 0); // clear Timmer on unmount return () => { clearTimeout(timer); }; } }, [myAction]) //... return <p>{loadingStatus}</p><button onClick={() => setMyAction({})} />Las devoluciones de llamada useEffect solo pueden devolver una función undefined o destructora. En su ejemplo, ha pasado una función asíncrona que devuelve una Promesa. Puede ejecutarse o no, pero verá advertencias de React de que las devoluciones de llamada de useEffect se ejecutan sincrónicamente.
En su lugar, defina una función asíncrona y luego llámela.
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({})} />De lo contrario, lo que ha escrito funcionará.