I have a simple file upload utility, for which I am using react-dropzone, and in conjunction to that I wanted to use material-ui LinearProgress bar to show the progress.
Complete example:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import Dropzone from "react-dropzone";
import request from "superagent";
import { Line } from 'rc-progress';
class App extends Component {
state = {
completed: 0
}
onDrop = files => {
this.setState({ completed: 0 });
var data = new FormData();
files.forEach(file => {
data.append("files[]", file, file.name);
});
var req = request.post("http://localhost:3001");
req.on('progress', event => {
var percent = Math.floor(event.percent);
if (percent >= 100) {
this.setState({ completed: 100 });
} else {
this.setState({ completed: percent });
}
});
const that = this;
req.send(data);
req.end((err, res) => {
console.log("Successfully uploaded");
});
};
render() {
const divStyle = {
border: '1px solid black'
};
return (
<div style={divStyle}>
<Dropzone onDrop={this.onDrop} className="dropzone-box">
<div>Try dropping some files here, or click to select files to upload. {this.state.completed}</div>
<Line percent={this.state.completed} strokeWidth="0.5" strokeColor="#2db7f5" strokeLinecap="square" />
</Dropzone>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
Firstly, I think your problem might be this:
onDrop={this.onDrop}
should be
onDrop={files => this.onDrop(files)}
or...
onDrop={this.onDrop.bind(this)}
or...
constructor(props) {
super(props);
this.state = {
completed: 0,
};
this.onDropHandler = this.onDrop.bind(this);
}
// ... then on your component:
onDrop={this.onDropHandler}
...otherwise, all your "this" references inside of onDrop() won't be correct, so "this.state" and "this.setState" would fail.
But also, you should never mutate your state directly. Always use setState(). So, remove all calls like this:
this.state.completed = ???;
always do this instead:
this.setState({ completed: ??? });
Also, setState is asynchronous. So, if you need to have something fired only after the state has been updated, you can pass a callback function as the 2nd argument:
this.setState({ completed: 75 }, () => { console.log('state.completed is now 75'));
// ^^ Immediately after the above call state.completed is probably not 75 yet,
// because setState() is async
Lastly, pay particular attention to your req.end() call. In there, you are only mutating the state (again, that's bad) and you are not calling .setState() at all (hence, the component won't be re-rendered after req.end() )