I try to report to the user the progress of the promise execution. The problem I’m encountering is that React seems to be merging my setState
calls into a single render.
When I click start, it flashes 0 / 5
and then stays 1 / 5
, and other times it comes up higher than 1. There is also a problem with execution stopping when the button is pressed, because setState
doesn’t have time to update total
and thus stops the code before the button is pressed (the commented line). The code below is my attempt.
import React, { useState } from "react";
export default function ({}) {
const [state, setState] = useState({ progress: 0, total: 0 });
const wait = (duration) => () => new Promise((resolve) => setTimeout(resolve, duration));
const startWork = async () => {
const tasks = [wait(100), wait(200), wait(300), wait(400), wait(500)];
setState({ ...state, progress: 0, total: tasks.length });
for (const task of tasks) {
// stop if cancelled
// if (state.total === 0) return;
const data = await task();
setState({ ...state, progress: state.progress + 1 });
}
};
const cancelWork = () => {
setState({ ...state, total: 0 });
};
return (
<div>
<p>
{state.progress} / {state.total}
</p>
<button onClick={startWork}>Start</button>
<button onClick={cancelWork}>Cancel</button>
</div>
);
}