11

I want is to show a progressbar while Axios is getting my requests. axios package has both onDownloadProgress and onUploadProgress to show a progressbar during download or upload, but no progress bar during get request. I've searched a lot of questions and articles but they are always about download/upload progress or for Vue.js and I fail to understand how to do it in React.

I have the following code down below (which will not work because I'm not downloading).

Ideally, I'd write it myself; but I'm willing to consider using axios-progress package if someone could explain me how I'd integrate the loadProgressBar() with my Axios request.

request = () => {
    this.setState({error: null, results: []})
    axios({
        method: 'get',
        url: process.env.REACT_APP_API_LOCALS,
        responseType: 'json',
        onDownloadProgress: (progressEvent) => {
            var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
            this.setState({
                loading: percentCompleted
            })
        },
    })
    .then(
        (response) => {
            console.log(response)
            this.setState({
                results: response.data.results,
                error: null,
                totalPages: Math.ceil(response.data.count / response.data.results.length)
            })  
        }
    )
    .catch(
        (error) => {
            this.setState({
                loading: null,
                error: true
            })  
        }
    );
}
Ken White
  • 117,855
  • 13
  • 197
  • 405
Cédric Bloem
  • 906
  • 2
  • 9
  • 29

4 Answers4

12

Here's what worked for me in React:

const client = axios.create({
  baseURL: 'http://localhost:10000/v1/client',
  timeout: 20000
})

let result = await client.get('/fetchMeSomething', {
  onDownloadProgress: progressEvent => {
    const total = parseFloat(progressEvent.currentTarget.responseHeaders['Content-Length'])
    const current = progressEvent.currentTarget.response.length

    let percentCompleted = Math.floor(current / total * 100)
    console.log('completed: ', percentCompleted)
  }
})
.then(res => {
  console.log("All DONE: ", res.headers)
  return res.data
})
KBog
  • 1,454
  • 19
  • 25
  • 6
    You can also use `let percentCompleted = Math.floor(progressEvent.loaded / progressEvent.total * 100)`, so no need to parse and look into headers. – Simons0n Aug 29 '20 at 13:43
0

I think the reason why axios exposes both onUploadProgress and onDownloadProgress is that you can easily perform some calculation on bytes being transferred. In case of simple server request, I think using a flag such as setting on

state = {
  loading: false
}

and flip this to true whenever you make your request is ideal. You may use a spinner as a mask if you wish to.

tbuglc
  • 180
  • 9
  • The spinner I know how to do, indeed, it's an easy switch from false to true. However, I have at least 7 pages with different requests of a lot of data. Instead of a spinner, I find this case needs a progress bar so users know how long it'll take for content to load. – Cédric Bloem Jan 16 '19 at 09:32
  • 1
    Have you thought of using `Suspense` and `React.lazy`? I think this is right thing to do in this case (if I'm not wrong), progressively loading pages as user navigate through them rather than load them all at once. It also improves user experience. – tbuglc Jan 16 '19 at 09:41
  • I think it certainly would be interesting to use! And in that case, I think a simple spinner will do. However; because I have not yet found an answer to this specific question neither in articles nor on Stackoverflow, I'm going to leave this open for a while so future React developers who come across the same problem may find a solution here. Thanks for the Suspense / React.lazy tip! [@tbuglc](https://stackoverflow.com/users/10918112/tbuglc) – Cédric Bloem Jan 16 '19 at 09:54
  • 1
    You're welcome. You may also find this talk by **Andrew Clark** `Concurrent Rendering in React`[https://www.youtube.com/watch?v=ByBPyMBTzM0] interesting – tbuglc Jan 16 '19 at 09:55
0

I know you asked for a progress bar, but I've used this tutorial for creating a progress circle utilizing svg circles with the stroke-dasharray and stroke-dashoffset properties.

https://css-tricks.com/building-progress-ring-quickly/

The whole thing is done in React so it should be a pretty easy implementation for you.

0
   axios.get("download something", {
            onDownloadProgress: (progressEvent) => {
                let downloadCount = DownloadCount(progressEvent.timeStamp, progressEvent.total, progressEvent.loaded)
                let percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
                setProgressing(percentCompleted)
                dispatch({
                    type: 'downloading',
                    payload: downloadCount.toFixed(1)
                })
            }
        }).then((response) => {

        }).catch(error => {
            console.log(error);
        });
Owen Kelvin
  • 8,862
  • 4
  • 14
  • 36
  • Please have a read of [this](https://stackoverflow.com/editing-help) help page about how to format code properly. – costaparas Jan 03 '21 at 06:28