Titan
Titan

Reputation: 6040

React, how to update state fast

What would be the recommended way to display a rapidly changing value in React, e.g upload progress? In my axios config I have

onUploadProgress: progressEvent => {
    let percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total )
    this.setState({ avatarUploadPercentage: percentCompleted })
}

<span>Upload progress: {this.state.avatarUploadProgress}</span>

but setState doesn't like being called that quickly of course, and won't guarantee order. Should I use refs instead and change the inner html myself?

Upvotes: 9

Views: 5307

Answers (3)

luanped
luanped

Reputation: 3198

What do you want to do with the value of avatarUploadPercentage ? If you need to display the actual number, then as suggested in the other answer you could either debounce setState or modify the dom directly.

However if it's displaying a progress bar being filled, it could be done using CSS, although still modifying the element via ref, but not triggering a whole component lifecycle (wasteful)

Something like [refToProgressBarElement].style.width = `${avatarUploadPercentage}%`

Upvotes: 0

skylerfenn
skylerfenn

Reputation: 354

How about limiting when the onUploadProgress callback runs? You can wrap your callback in a "debounce" function which limits the frequency a callback will run. Underscore and Lodash offer debounce methods.

Once per second:

onUploadProgress: debounce(progressEvent => {
    let percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total )
    this.setState({ avatarUploadPercentage: percentCompleted })
}, 1000)

See plain debounce function from https://davidwalsh.name/javascript-debounce-function.

Upvotes: 4

aecend
aecend

Reputation: 2462

I'd recommend using a ref to access the element that is displaying the progress. Calling setState for that case is a bit wasteful on the rendering side if it's just a progress bar/value that is changing. Call setState when the upload begins to display progress, then setState again to hide it after it's complete.

Upvotes: 3

Related Questions