Mi objetivo es aumentar gradualmente la barra de progreso cuando haya pasado un tiempo después de crear un pedido. Para hacer esto, me gustaría llamar a la función asíncrona updateStatus a continuación en diferentes intervalos y con diferentes argumentos hasta que el estado progress llegue a 100. A continuación, pegué el código para la barra de progreso.
Al encadenar setTimeOut y Promise , la barra de progreso aumentaba y disminuía aleatoriamente, lo que provocaba que la aplicación se ralentizara o congelara. ¿Cuál es la forma correcta de manejar lo que estoy tratando de lograr?
const ProgressBar = ({ order }) => { const { status, order_date } = order; const msTillXSeconds = (seconds) => new Date(moment(order_date).add(seconds, 'seconds')).getTime() - Date.now(); const [progress, setProgress] = useState(progression[status]); const [internalStatus, setInternalStatus] = useState(status); const updateStatus = async (newStatus) => { try { const body = { status: newStatus }; const response = await fetch(`http://localhost:5000/orders/${order.order_id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', token: localStorage.token }, body: JSON.stringify(body), }); if (response.ok) { setProgress(progression[newStatus]); setInternalStatus(newStatus); } } catch (err) { console.error(err.message); } }; useEffect(() => { setProgress(progression[status]); }, []); return ( <> <div className="progress"> <div className="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style={{ width: `${progress}%` }} > {' '} </div> </div> <p className="text-center my-1">{internalStatus}</p> </> ); }; const STAGES = { PENDING: 'Pending Order Confirmation', CONFIRMED: 'Order Confirmed', PICKING_UP: 'Picking Up', EXAMINING: 'Examining', SANITIZING: 'Sanitizing', RECYCLING: 'Recycling', }; const progression = { [STAGES.PENDING]: 5, [STAGES.CONFIRMED]: 20, [STAGES.PICKING_UP]: 40, [STAGES.EXAMINING]: 60, [STAGES.SANITIZING]: 70, [STAGES.RECYCLING]: 100, };Puede pasar diferentes argumentos a su función como un tercer argumento de setTimeout.
setTimeout(updateStatus, 1000, ...args) (usando su estado internalStatus como status en mi ejemplo)
Además, dado que el estado está en su estado, puede manejar un próximo setTimeout en un gancho useEffect() según su lógica.
useEffect(() => { if status something otherStatus = somethingElse updateOtherStatusAfter = ... setTimeout(updateStatus, updateOtherStatusAfter, otherStatus) }, [ status ] )Observe que el estado está en la lista de dependencias de useEffect.
Esto significa que cada vez que cambie el estado, se activará la función que pase dentro de useEffect.
Después de un comentario de Drew Reese sobre la limpieza, considera algo como esto.
useEffect(() => { const tId = setTimeout(...) return () => { clearTimeout(tId) } }, [ ... ] )Si entiendo correctamente su problema, desea llamar periódicamente a updateStatus Y asegurarse de que se respete el orden de llamada de updateStatus.
Para esto veo dos soluciones:
En cualquier caso, deberá limpiarlos cuando se desmonte el componente.