Carlos Silva
Carlos Silva

Reputation: 101

Preview multiple drop using react-dropzone

I'm trying to implement Dropzone on my app but I can't preview photos if they are drop as a multiple input. If I add them one by one it works fine but if I select multiple only the first one gets rendered.

This is my onDrop function

onDropGeneral = (currentGeneralPhoto) => {
 let index;
 for (index = 0; index < currentGeneralPhoto.length; ++index) {
  const file = currentGeneralPhoto[index];
  this.setState({
    previewGeneralPhotos: this.state.previewGeneralPhotos.concat(file)
  });
  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onload = (event) => {
    console.log('URL: ', event.target.result);
    this.setState({
      generalPhotos: this.state.generalPhotos.concat([{ base64: event.target.result }])
    });
  };
 }
}

and this is my render method:

<h2>Dropped files</h2>
{this.state.previewGeneralPhotos.length > 0 ? <div>
  <h2>Preview {this.state.previewGeneralPhotos.length} files...</h2>
  <div>{this.state.previewGeneralPhotos.map((file) => <img src={file.preview} alt="preview failed" />)}</div>
 </div> : null}
 <h2> Upload {this.state.generalPhotos.length} Files </h2>

the Upload count is showing the right size of the array but the Preview count only counts the 1st photo dropped

Upvotes: 2

Views: 2547

Answers (1)

Jon Rubins
Jon Rubins

Reputation: 4423

So your issue is because setState can be asynchronous. You should use the function callback for setState as follows in your onDropGeneral function:

this.setState(({ previewGeneralPhotos }) => ({
  previewGeneralPhotos: previewGeneralPhotos.concat(file)
}))

This will make sure you don't accidentally overwrite the previous value of previewGeneralPhotos and you actually add to the existing array as you intend.

A couple of other suggestions:

  • Make sure your img elements have a key.
  • I would use an instance of the file reader for the entire Component instead of creating a new one each time your onDropGeneral method is called. You could attach an event listener for the 'load' event in componentDidMount and remove that listener in componentWillUnmount. At the very least, it's probably best to attach that event listener before calling reader.readAsDataURL.

Upvotes: 1

Related Questions