2

I have a react component in which user can upload Image and he's also shown the preview of uploaded image. He can delete the image by clicking delete button corresponding to Image. I am using react-dropzone for it. Here's the code:

class UploadImage extends React.Component {
  constructor(props) {
    super(props);
    this.onDrop = this.onDrop.bind(this);
    this.deleteImage = this.deleteImage.bind(this);
    this.state = {
      filesToBeSent: [],
      filesPreview: [],
      printCount: 10,
    };
  }

  onDrop(acceptedFiles, rejectedFiles) {
    const filesToBeSent = this.state.filesToBeSent;
    if (filesToBeSent.length < this.state.printCount) {
      this.setState(prevState => ({
        filesToBeSent: prevState.filesToBeSent.concat([{acceptedFiles}])
      }));
      console.log(filesToBeSent.length);
      for (var i in filesToBeSent) {
        console.log(filesToBeSent[i]);
        this.setState(prevState => ({
          filesPreview: prevState.filesPreview.concat([
            <div>
              <img src={filesToBeSent[i][0]}/>
              <Button variant="fab" aria-label="Delete" onClick={(e) => this.deleteImage(e,i)}>
                <DeleteIcon/>
              </Button>
            </div>
          ])
        }));
      }
    } else {
      alert("you have reached the limit of printing at a time")
    }
  }

  deleteImage(e, id) {
    console.log(id);
    e.preventDefault();
    this.setState({filesToBeSent: this.state.filesToBeSent.filter(function(fid) {
        return fid !== id
    })});
}

  render() {
    return(
      <div>
        <Dropzone onDrop={(files) => this.onDrop(files)}>
          <div>
            Upload your Property Images Here
          </div>
        </Dropzone>
        {this.state.filesToBeSent.length > 0 ? (
          <div>
            <h2>
              Uploading{this.state.filesToBeSent.length} files...
            </h2>
          </div>
        ) : null}
        <div>
          Files to be printed are: {this.state.filesPreview}
        </div>
      </div>
    )
  }
}

export default UploadImage;

My Question is my component is not re-rendering even after adding or removing an Image. Also, I've taken care of not mutating state arrays directly. Somebody, please help.

uneet7
  • 2,925
  • 7
  • 24
  • 41
  • 2
    Consider providing a working demo to debug. `(files) => this.onDrop(files)` is redundant, a callback is already bound. `prevState.filesToBeSent.concat([{acceptedFiles}])` - this looks fishy, there will be an object with `acceptedFiles` property. It doesn't look there's a need for it. Shouldn't it be `[...prevState.filesToBeSent, ...acceptedFiles]`? – Estus Flask Sep 29 '18 at 07:50

1 Answers1

4

Try like this, I have used ES6

Edit 7myoo2x226 .

Nisfan
  • 750
  • 6
  • 10
  • 1
    Thank you so much, sir! So you moved the function for displaying image previews inside render. Also, you updated the way of changing states. But can you explain me why my way of changing state was wrong in onDrop() function? – uneet7 Sep 29 '18 at 18:23
  • 1
    You have to think and code in react way not jQuery way like constructing html and append html into element and also keeping html in state isn't necessary in your case which cause unnessary complexity if you have large html – Nisfan Sep 29 '18 at 19:05
  • I have one more doubt... Didn't you mutate the state array directly in `deleteImage()` function. Sorry for the too mainstream questions as I am totally new to React – uneet7 Sep 30 '18 at 05:35
  • 1
    this.state.filesToBeSent.filter always return new array, check https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter – Nisfan Sep 30 '18 at 05:54