'Uploading multiple images in React
I would like to upload multiple images to send them off.
I tried this two ways in handleChange
but the formdata
is always empty.
I also want to know how to display the image in the react
state = { files: []}
fileChangeHandler = (e) => {
this.setState({ files: e.target.files })
this.setState({ files: [...this.state.files, ...e.target.files] })}
handleSubmit(event) {let fileData = new FormData();
fileData.append('files', this.state.files);
uploadClaimFile(response.data.id, fileData);}
the input
<input type="file" multiple onChange={this.fileChangeHandler} />
Solution 1:[1]
The safest way to append to a state
array without directly modifying it is to make a shallow copy of the array, add the new items, and then replace the array using setState
:
fileChangeHandler = (e) => {
const files = [...this.state.files]; // Spread syntax creates a shallow copy
files.push(...e.target.files); // Spread again to push each selected file individually
this.setState({ files });
}
As for uploading the files, when appending to a FormData
object you must append the files one at a time:
handleSubmit(event) {
const fileData = new FormData();
this.state.files.forEach((file) => fileData.append('files[]', file));
// ... Submit fileData
}
Note: The use of []
in naming the data is in accordance with PHP naming conventions when uploading multiple files.
Edit
To answer your last question about displaying multiple uploaded files, you would want to write a method to take those files, create URLs that tie them back to the document, and display them. However, created URLs must be revoked to prevent memory leaks. Thus, it might be a good idea to store them in state to keep track of them, so you can implement it like this:
this.state = { files: [], urls: [] };
setFileUrls(files) {
const urls = files.map((file) => URL.createObjectURL(file));
if(this.state.urls.length > 0) {
this.state.urls.forEach((url) => URL.revokeObjectURL(url));
}
this.setState({ urls });
}
displayUploadedFiles(urls) {
return urls.map((url, i) => <img key={i} src={url}/>);
}
Call setFileUrls
in your onChange
handler, and call displayUploadedFiles
in the render method:
render() {
return (
// ... other stuff
{this.state.urls.length > 0 &&
<Fragment>{this.displayUploadedFiles(this.state.urls)}</Fragment>
}
// ... more stuff
);
}
Multiple adjacent elements should be wrapped in a parent element, which can be a div
or a React Fragment.
Solution 2:[2]
You can explore this npm module React Drop Zone.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Prabhat Mishra |