'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