I have this function on a React component
handleChangeImage: function (evt) {
console.log("Uploading");
var self = this;
var reader = new FileReader();
var file = evt.target.files[0];
reader.onload = function(upload) {
self.setState({
image: upload.target.result
});
};
reader.readAsDataURL(file);
console.log(this.state.image);
console.log("Uploaded");
},
and is called here
<input ref="file" type="file" name="file"
className="upload-file"
id="file"
onChange={this.handleChangeImage}
encType="multipart/form-data"
required/>
I'm trying to get the base64 string to send via AJAX to a server running Flask. The problem is everytime I select a file, it is logged as null in the console
Funny thing is, if I try to select the file a second time it now logs the whole string. I must be missing something simple...
Try this one
Input field
<MyTextField
id="originalFileName"
type="file"
inputProps={{ accept: 'image/*, .xlsx, .xls, .csv, .pdf, .pptx, .pptm, .ppt' }}
required
label="Document"
name="originalFileName"
onChange={e => this.handleFileRead(e)}
size="small"
variant="standard"
/>
Read File from computer
handleFileRead = async (event) => {
const file = event.target.files[0]
const base64 = await this.convertBase64(file)
console.log(base64)
}
Base64 Converter function
convertBase64 = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file)
fileReader.onload = () => {
resolve(fileReader.result);
}
fileReader.onerror = (error) => {
reject(error);
}
})
}
It is logged as null in the console because the state hasn't been changed at the time you print it out. When you select the file second time, the string logged in console actually belongs to the previous file you selected. The state is not yet changed to the second file you select.
Referring to React's doc:
setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.
If you want to print the correct state, you may log it in the callback function:
self.setState({
image: upload.target.result
}, function() {
console.log(self.state.image);
});
This will also work as the state should be changed after the 1s delay:
reader.onload = function(upload) {
self.setState({
image: upload.target.result
});
};
reader.readAsDataURL(file);
setTimeout(function() {
console.log(self.state.image);
}, 1000);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With