Reputation: 12054
I have one strange problem by uploading files using React JS.
The main component is as follows:
class Test extends React.Component {
constructor(props){
super(props);
this.state = {
files: [
{file_type: registrationFormFields.ID_CARD.key, values: {active: false, fileName: language.btnIdCard, file: null, base64: ""}},
{file_type: registrationFormFields.STATUTES.key, values: {active: false, fileName: language.btnStatut, file: null, base64: ""}},
{file_type: registrationFormFields.BLANK_LETTER_HEAD.key, values: {active: false, fileName: language.btnBlanco, file: null, base64: ""}},
{file_type: registrationFormFields.COMPANY_PHOTO.key, values: {active: false, fileName: language.btnCompanyPhoto, file: null, base64: ""}}
]
};
}
handleFiles(file_type, event){
event.preventDefault();
let self = this;
let fileValue = event.target.value;
let files = "";
let file = event.target.files[0];
let filename = file.name.substr(0, file.name.lastIndexOf('.')) || file.name;
const size_in_mb = file ? file.size/1000000 : null;
if(this.fileIsValid(file_type, size_in_mb)){
if(fileValue){
this.getBase64(file, function(e){
let base64 = e.target.result;
let nState = self.state.files;
if(self.state.files.some(i => i.file_type === file_type))
nState = self.state.files.filter(f => f.file_type !== file_type);
files = [...nState, {file_type: file_type, values: {active: true, fileName: filename, file, base64: base64}}];
self.setState({files: files});
});
}
}
}
removeFile = (file_type, file_name) => {
let nState = this.state.files;
let nFiles = this.state.files;
if(this.state.files.some(i => i.file_type === file_type)){
nState = this.state.files.filter(f => f.file_type !== file_type);
nFiles = [...nState, {file_type: file_type, values: {active: false, fileName: file_name, file: null, base64: ""}}];
}
this.setState({files: nFiles});
};
render(){
return (
<FileInputButton pictureIcon="credit-card"
onFileChange={this.handleFiles.bind(this, registrationFormFields.ID_CARD.key)}
btnName="idCard"
extraClass="col-lg-offset-2 col-md-offset-2 col-sm-offset-2"
fileType={registrationFormFields.ID_CARD.key}
fileName={language.btnIdCard}
removeFile={this.removeFile}
errors={this.state.errors[registrationFormFields.ID_CARD.key]}
values={this.getValues(registrationFormFields.ID_CARD.key)}/>
)
}
}
React.render(<Test />, document.getElementById('container'));
There is more code but this is the important one.
And FileInputButton
component is as follows:
const FileInputButton = ({extraClass, pictureIcon, btnName, onFileChange, values, removeFile, fileType, fileName, errors}) => {
const name = values.fileName === fileName ? `Add ${fileName}` : `Added ${fileName}`;
const icon = values.active ? "check" : "upload";
let borderClass = "";
if(values.active) borderClass = "fileSuccess";
if(errors) borderClass = "fileError";
let removeButton = "";
if(values.active){
removeButton = <div className="remove-file" onClick={() => removeFile(fileType, fileName)}><Ionicon icon="ios-close" fontSize="22px" color={styles.errorColor}/> Remove</div>
}
let added_file = "";
if(values.active){
added_file = <div className="added-file-name"><Ionicon icon="ios-checkmark" fontSize="22px" color={styles.successColor}/>{values.file.name}</div>
}
return (
<div className={`col-lg-4 col-md-4 col-sm-4 ${extraClass}`}>
<div className="picture-container" style={{marginLeft: 18}}>
<div className={`picture ${borderClass}`}>
<FontAwesome name={pictureIcon} size="3x" className="picture-src"/>
</div>
</div>
<div className="uploadButtonBox" style={{width: '100%', textAlign: 'center', marginTop: 20}}>
<label className={`fileUploadButton ${borderClass}`}>
<FontAwesome name={icon} className="faIcon" style={{height: '39px !important'}}/>
<span className={`btnFileText ${btnName}`}>{name}</span>
<input id="btnFile" type="file" style={{display: 'none'}} onChange={onFileChange} name={name}/>
</label>
</div>
{added_file}
{removeButton}
<div className="errorBox">{errors}</div>
</div>
);
};
Everything works fine. There is only one scenario when it doesn't work as expected.
If the file is chosen little remove
button (the removeButton from FileInputButton
component) is shown. If I click on it the removeFile
function from main component gets called, and I change the state (find that file in state, remove it, and add a new object with initial values for that file and then update the state).
The file is removed and everything works fine. If I new add a new file, that works also as expected. The problem is if I try to add the same file again, then it doesn't work. The handleFiles
function isn't called at all.
If I add first file and then remove it, then add new second file then remove the second file and then again add the first file it works fine.
Only problem is if I add first file, then remove it and then try to add it again it doesn't work. I do not get any errors in console.
Any idea what I do wrong?
Upvotes: 0
Views: 1444
Reputation: 2406
You have onChange handler on your file input, however when you clear file from your state, you are not clearing it from your input. So when you are trying to upload the same file again, onChange event is not triggered therefore your handler is not called.
Put your input file value to '' to reset it.
Lets say that your delete handler would look like this.
handleDelete(){
document.querySelector('input[type=file]').value = '';
this.props.removeFile(this.props.fileType, this.props.fileName);
}
This code may be not entirely in the spirit of your code, but you will get the point.
Upvotes: 2