通过使用React JS上传文件,我遇到了一个奇怪的问题。
主要组成部分如下:
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'));
还有更多代码,但这是重要的代码。
FileInputButton
组件如下:
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>
);
};
一切正常。只有一种情况不能按预期工作。
如果选择了文件,则显示小remove
按钮(来自FileInputButton
组件的removeButton)。如果我点击它,主要组件的removeFile
函数被调用,我改变状态(找到该状态的文件,将其删除,并添加一个具有该文件初始值的新对象,然后更新国家)。
该文件已删除,一切正常。如果我新添加一个新文件,它也可以按预期工作。问题是,如果我尝试再次添加相同的文件,那么不工作。根本没有调用handleFiles
函数。
如果我添加第一个文件然后将其删除,则添加新的第二个文件,然后删除第二个文件,然后再添加第一个文件,它可以正常工作。
唯一的问题是,如果我添加第一个文件,然后删除它,然后尝试再次添加它不起作用。我在控制台中没有任何错误。
知道我做错了吗?
答案 0 :(得分:2)
您的文件输入上有onChange处理程序,但是当您从状态清除文件时,您不会从输入中清除它。因此,当您尝试再次上载同一文件时,不会触发onChange事件,因此不会调用您的处理程序。
将输入文件值设为''以重置它。
假设您的删除处理程序看起来像这样。
handleDelete(){
document.querySelector('input[type=file]').value = '';
this.props.removeFile(this.props.fileType, this.props.fileName);
}
这段代码可能并非完全符合您的代码精神,但您会明白这一点。