Reputation: 531
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?
Upvotes: 1
Views: 82
Reputation: 108
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);
}
Upvotes: 1