The code below is the one that I'm currently working on. What it does is to receive a file as a user input and send an axios post request, and through Spring Boot backend the passed file will be stored in a folder in my PC's C drive.
import React from 'react'
import { post } from 'axios';
class SimpleFileUpload extends React.Component {
constructor(props) {
super(props);
this.state ={
file:null
}
this.onFormSubmit = this.onFormSubmit.bind(this)
this.onChange = this.onChange.bind(this)
this.fileUpload = this.fileUpload.bind(this)
}
onFormSubmit(e){
e.preventDefault() // Stop form submit
this.fileUpload(this.state.file).then((response)=>{
console.log(response.data);
})
}
onChange(e) {
const chosenFile = e.target.files[0];
this.setState({file:chosenFile});
}
fileUpload(file){
const url = 'http://localhost:8080/report/uploadFile';
const formData = new FormData();
formData.append('file',file)
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
return post(url, formData,config)
}
render() {
return (
<form onSubmit={this.onFormSubmit}>
<h1>File Upload</h1>
<input type="file" onChange={this.onChange} />
<button type="submit">Upload</button>
</form>
)
}
}
export default SimpleFileUpload
The problem was that setState
was performed asynchronously within the onChange
method and and when I clicked the Upload
button to trigger the onFormSubmit
method, the file
inside this.state
was null
and axios.post
request failed.
I managed to have the post request successfully work by modifying the onChange
method like below, whose idea is something close to using a callback function,
onChange(e) {
const chosenFile = e.target.files[0];
this.setState({file:chosenFile});
this.fileUpload(chosenFile).then((response)=>{
console.log(response.data);
})
}
but the problem with this way is that the post request gets sent even without clicking the Upload
button.
I tried to wrap the setState
with an await
feature by adding the two methods below,
setStateSynchronous(stateUpdate){
return new Promise(
this.setState({file:stateUpdate})
)
}
async callSynchSetState(stateUpdate){
await this.setStateSynchronous(stateUpdate);
}
and mofified the onChange
method like below, but it didn't work.
onChange(e) {
const chosenFile = e.target.files[0];
//this.setState({file:chosenFile});
this.callSynchSetState(chosenFile);
/*this.fileUpload(chosenFile).then((response)=>{
console.log(response.data);
}) */
}
Any idea on how to send the chosen file only if the Upload
button is clicked?
Your attempt to wrap the setState
is not completely wrong. You just needed to write more succinctly.
Instead of
setStateSynchronous(stateUpdate){
return new Promise(
this.setState({file:stateUpdate})
)
}
async callSynchSetState(stateUpdate){
await this.setStateSynchronous(stateUpdate);
}
, just wrap the setState
like so
async awaitSetState(stateUpdate){
await this.setState({file:stateUpdate})
}
, and then just call that method in onChange
method like so
onChange(e) {
const chosenFile = e.target.files[0];
this.awaitSetState(chosenFile);
}