Reputation: 1195
[First of all I need to tell that I'm a beginner in ReactJS]
There is a web API that I'm using for creating employee data. With that API, I'm sending employee data array.
http://localhost:5000/api/services/app/Employee/AddEmployees
Input json looks a like,
[{
"id": 5495,
"employeeName": "Sarwen",
"department": "Production",
"factoryLocation": "Denmark"
},
{
"id": 5496,
"employeeName": "Kate",
"department": "HR",
"factoryLocation": "Denmark"
}
.
.
.
.
.
.
.]
There are thousands of data in above json.
The web API got all the data at once and then process inside the server. It works totally fine.
public async Task<bool> AddEmployees(InputDto input)
{
//inserting to DB
}
But it took a little time to process. The issue is, the front end user doesn't know the status of that process. (Front end user have no idea, how many records remaining in the process).
I'm developing a React js application for doing above. This is how I send data to API.
async function saveEmployees(props) {
var data = {
Token : usr
EmpData: props//props will get the employee data set
}
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
};
const response = await fetch('http://localhost:5000/api/services/app/Employee/AddEmployees', requestOptions);
};
I need to show a kind of progress bar or a percentage. I checked for few progress bar options in ReactJS and it needs a percentage for showing the progress bar. Can any expert help me out of this for showing a progress bar regarding my scenario? Need to get current running (real time) record index or whatever progress to the front end.
Upvotes: 0
Views: 4466
Reputation: 3227
You have a few options, which one works best depends on the back end implementation.
Unless the data needs to all be submitted at the same time, this is probably the easiest and best option. As your code already loads the data in memory in JS, there's not much code needed to turn it into a loop. Then you can just update the progress bar every time a part finishes.
If you use state, you can just pass the setter of the variable holding the done percentage as an argument to your async function, it's always the same function.
async function uploadBatched (setProgress) {
for (let i = 0; i < items.length; i+=batchSize) {
const chunk = items.slice(i, i + batchSize);
await saveEmployees(chunk);
setProgress(100 * i / items.length )
}
}
The code in the snippet below is a bit different/mangled because SO snippets can't have React and async together :( I did a hack with .then()
that should have the same behavior as an async loop.
const {useState, useEffect} = React;
// Generate example data.
const data = Array.from(Array(1000).keys());
const batchSize = 100;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function saveEmployees(items) {
return sleep(10 * items.length);
};
function uploadBatched(items, setProgress) {
let previous;
console.log(items);
for (let i = 0; i < items.length; i+=batchSize) {
// Workaround code, please read the async version of uploadBatched instead.
// I also cheat and add batchSize, to avoid needing a complex fix for the last batch.
const doBatch = () => {
setProgress(100 * (i+batchSize) / items.length )
const chunk = items.slice(i, i + batchSize);
console.log();
return saveEmployees(chunk);
}
if (previous) {
previous = previous.then(doBatch)
} else {
previous = doBatch();
}
}
}
function App() {
const [progress, setProgress] = useState(0);
return <div>
<button onClick={()=>{uploadBatched(data,setProgress)}}>Upload</button>
<div className="progress-container">
<div style={{width: `${progress}%`}} className="progress">{progress}%</div>
</div>
</div>
}
const root = document.getElementById('root');
ReactDOM.render(<App/>, root);
.progress-container {
border: 1px solid black;
position: relative;
width: 240px;
height: 42px;
}
.progress {
height: 100%;
background: lightgreen;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You could send a request and create an asynchronous job to process the data, instead of letting the request wait for a response. The server just acknowledges it has received the request and will asynchronously process it.
Then you can poll a server endpoint that gives the current processing status and set the scrollbar size with it.
From the front end POV this is not harder than the first approach, but the back end infrastructure needs to be there.
Upvotes: 0