Reputation: 7202
I am trying to apply Dropzone bootstrap example under ReactJS as shown in the code below.
But for some reason, the Start Upload / Cancel Upload and progress bars are behaving in an inconsistent way.
Example 1: Progress bar shows endless progress even if I cancelled all files to be uploaded. Example 2: Start upload single file won't do anything.
Can someone please tell me what I am doing wrong/missing here and how can I make this work just like the example?
Note: Based on first reply if possible using Refs
import React from 'react';
import { connect } from 'react-redux';
@connect((state) => state)
export default class DZUploader extends React.Component {
componentDidMount() {
let previewNode = document.querySelector("#template");
previewNode.id = "";
let previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
let myDropzone = new Dropzone(document.body, {
url: "/target-url", // Set the url
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 2, // MB
thumbnailWidth: 80,
thumbnailHeight: 80,
parallelUploads: 20,
previewTemplate: previewTemplate,
autoQueue: false,
previewsContainer: "#previews",
clickable: ".fileinput-button",
});
myDropzone.on('addedfile', function(file){
console.log(file);
file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
});
myDropzone.on('totaluploadprogress', function(progress){
console.log(progress);
document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
});
myDropzone.on('sending', function(file){
// Show the total progress bar when upload starts
document.querySelector("#total-progress").style.opacity = "1";
// And disable the start button
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
myDropzone.on('queuecomplete', function(progress){
document.querySelector("#total-progress").style.opacity = "0";
});
document.querySelector("#actions .start").onclick = function() {
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
};
document.querySelector("#actions .cancel").onclick = function() {
myDropzone.removeAllFiles(true);
};
}
render() {
return (
<div>
<div id="actions" className="row">
<div className="col-lg-7">
<span className="btn btn-success fileinput-button dz-clickable">
<i className="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
</span>
<button type="submit" className="btn btn-primary start">
<i className="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" className="btn btn-warning cancel">
<i className="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
</div>
<div className="col-lg-5">
<span className="fileupload-process">
<div id="total-progress" className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div className="progress-bar progress-bar-success" data-dz-uploadprogress=""></div>
</div>
</span>
</div>
</div>
<div className="table table-striped" className="files" id="previews">
<div id="template" className="file-row">
<div>
<span className="preview"><img data-dz-thumbnail /></span>
</div>
<div>
<p className="name" data-dz-name></p>
<strong className="error text-danger" data-dz-errormessage></strong>
</div>
<div>
<p className="size" data-dz-size></p>
<div className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div className="progress-bar progress-bar-success" data-dz-uploadprogress></div>
</div>
</div>
<div>
<button className="btn btn-primary start">
<i className="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
<button data-dz-remove className="btn btn-warning cancel">
<i className="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button data-dz-remove className="btn btn-danger delete">
<i className="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div>
</div>
</div>
);
}
}
Upvotes: 5
Views: 2939
Reputation: 4090
3 things:
By using componentDidMount lifecycle method doesn't mean that both $
(JQuery) and dropzone
are already loaded in the DOM
Use React Refs
instead of selectors so your components are consistent
You should import the dropzone
object with the import key and avoid the jquery dependency (import dropzone from 'dropzone'
).
Conclusion:
Avoid using Jquery when you don't need it, at least in this case.
As a conclusion to my suggestions your component should look like this:
import React from 'react';
import { connect } from 'react-redux';
import Dropzone from 'dropzone';
@connect((state) => state)
export default class DZUploader extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
this.onAddedfile = this.onAddedfile.bind(this);
this.onTotaluploadprogress = this.onTotaluploadprogress.bind(this);
this.onSending = this.onSending.bind(this);
this.onQueuecomplete = this.onQueuecomplete.bind(this);
this.onActionStartClick = this.onActionStartClick.bind(this);
this.onActionCancelClick = this.onActionCancelClick.bind(this);
}
componentDidMount() {
const previewNode = this.divTemplate;
previewNode.id = "";
const previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
const myDropzone = new Dropzone(document.body, {
url: "/target-url", // Set the url
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 2, // MB
thumbnailWidth: 80,
thumbnailHeight: 80,
parallelUploads: 20,
previewTemplate: previewTemplate,
autoQueue: false,
previewsContainer: "#previews",
clickable: ".fileinput-button",
});
myDropzone.on('addedfile', onAddedfile);
myDropzone.on('totaluploadprogress', onTotaluploadprogress);
myDropzone.on('sending', onSending);
myDropzone.on('queuecomplete', onQueuecomplete);
this.actionStart.onclick = onActionStartClick;
this.actionStart.onclick = onActionCancelClick;
}
onAddedfile(file) {
console.log(file);
file.previewElement.querySelector(".start").onclick = function() { myDropzone.enqueueFile(file); };
}
onTotaluploadprogress(progress) {
console.log(progress);
this.progressBar.style.width = progress + "%";
}
onSending(file) {
// Show the total progress bar when upload starts
this.totalProgress.style.opacity = "1";
// And disable the start button
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
}
onQueuecomplete(progress) {
this.totalProgress.style.opacity = "0";
}
onActionStartClick() {
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
}
onActionCancelClick() {
myDropzone.removeAllFiles(true);
}
render() {
return (
<div>
<div id="actions" className="row">
<div className="col-lg-7">
<span className="btn btn-success fileinput-button dz-clickable">
<i className="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
</span>
<button type="submit" className="btn btn-primary start" ref={(button) => { this.actionStart = button; }}>
<i className="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" className="btn btn-warning cancel" ref={(button) => { this.actionCancel = button; }}>
<i className="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
</div>
<div className="col-lg-5">
<span className="fileupload-process">
<div id="total-progress" ref={(div) => { this.totalProgress = div; }} className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div className="progress-bar progress-bar-success" ref={(div) => { this.progressBar = div; }} data-dz-uploadprogress=""></div>
</div>
</span>
</div>
</div>
<div className="table table-striped" className="files" id="previews">
<div id="template" ref={(div) => { this.divTemplate = div; }} className="file-row">
<div>
<span className="preview"><img data-dz-thumbnail /></span>
</div>
<div>
<p className="name" data-dz-name></p>
<strong className="error text-danger" data-dz-errormessage></strong>
</div>
<div>
<p className="size" data-dz-size></p>
<div className="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div className="progress-bar progress-bar-success" data-dz-uploadprogress></div>
</div>
</div>
<div>
<button className="btn btn-primary start">
<i className="glyphicon glyphicon-upload"></i>
<span>Start</span>
</button>
<button data-dz-remove className="btn btn-warning cancel">
<i className="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button data-dz-remove className="btn btn-danger delete">
<i className="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div>
</div>
</div>
);
}
}
Upvotes: 7
Reputation: 2460
The below is a demonstration of React + Dropzone + Relay usage.
Use Dropzone in your component.
<Dropzone style={{disply: 'none'}} disableClick={true} ref="dropzone" onDrop={this.onDrop}/>
Implement onDrop
function, here I'm doing a Relay mutation, if you are no using relay, then here should be making the post request to upload your file.
onDrop: function(files) {
/*
* TODO fire mutliple mutations triggars warnings
*/
files.forEach((file)=> {
Relay.Store.commitUpdate(
new AddImageMutation({
file,
images: this.props.User,
})
);
});
}
The above code can be found in relay-gallery
Live demo http://fanjin.computer/
Upvotes: 2