J'ai une entrée de téléchargement de fichier:
<input onChange={this.getFile} id="fileUpload" type="file" className="upload"/>
Et je gère le téléchargement de cette façon:
getFile(e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = (theFile) => {
var data = {
blob: theFile.target.result, name: file.name,
visitorId: this.props.socketio.visitorId
};
console.log(this.props.socketio);
this.props.socketio.emit('file-upload', data);
};
reader.readAsDataURL(file);
}
Si je télécharge le même fichier deux fois, l'événement upload n'est pas déclenché. Comment puis-je résoudre ce problème? Pour un code js simple, il suffisait de procéder comme suit: this.value = null; dans le gestionnaire de changement. Comment puis-je le faire avec ReactJS?
Je pense que vous pouvez simplement effacer la valeur d'entrée comme ceci:
e.target.value = null;
L'entrée de fichier ne peut pas être contrôlée, il n'y a pas de moyen spécifique de React pour le faire.
Ce travail pour moi - ref = {ref => this.fileInput = ref}
<input id="file_input_file" type="file" onChange={(e) => this._handleFileChange(e)} ref={ref=> this.fileInput = ref} />
puis dans mon cas une fois le fichier chargé sur le serveur, je l'efface en utilisant la déclaration ci-dessous
this.fileInput.value = "";
Ce qui a fonctionné pour moi a été de définir un attribut key
pour l'entrée de fichier. Lorsque j'ai besoin de le réinitialiser, je mets à jour la valeur de l'attribut clé:
functionThatResetsTheFileInput() {
let randomString = Math.random().toString(36);
this.setState({
theInputKey: randomString
});
}
render() {
return(
<div>
<input type="file"
key={this.state.theInputKey || '' } />
<button onClick={this.functionThatResetsTheFileInput()} />
</div>
)
}
Cela oblige React à restituer l’entrée à nouveau.
Vous pouvez également l'inclure dans votre élément d'entrée si vous savez que vous n'utiliserez pas du tout la valeur d'entrée du fichier intégré.
<input value={""} ... />
De cette façon, la valeur est toujours réinitialisée sur la chaîne vide lors du rendu et vous n'avez pas besoin de l'inclure maladroitement dans une fonction onChange.
Voici ma solution en utilisant le formulaire redux
class FileInput extends React.Component {
constructor() {
super();
this.deleteImage = this.deleteImage.bind(this);
}
deleteImage() {
// Just setting input ref value to null did not work well with redux form
// At the same time just calling on change with nothing didn't do the trick
// just using onChange does the change in redux form but if you try selecting
// the same image again it doesn't show in the preview cause the onChange of the
// input is not called since for the input the value is not changing
// but for redux form would be.
this.fileInput.value = null;
this.props.input.onChange();
}
render() {
const { input: { onChange, value }, accept, disabled, error } = this.props;
const { edited } = this.state;
return (
<div className="file-input-expanded">
{/* ref and on change are key properties here */}
<input
className="hidden"
type="file"
onChange={e => onChange(e.target.files[0])}
multiple={false}
accept={accept}
capture
ref={(input) => { this.fileInput = input; }}
disabled={disabled}
/>
{!value ?
{/* Add button */}
<Button
className="btn-link action"
type="button"
text="Add Image"
onPress={() => this.fileInput.click()}
disabled={disabled}
/>
:
<div className="file-input-container">
<div className="flex-row">
{/* Image preview */}
<img src={window.URL.createObjectURL(value)} alt="outbound MMS" />
<div className="flex-col mg-l-20">
{/* This button does de replacing */}
<Button
type="button"
className="btn-link mg-b-10"
text="Change Image"
onPress={() => this.fileInput.click()}
disabled={disabled}
/>
{/* This button is the one that does de deleting */}
<Button
type="button"
className="btn-link delete"
text="Delete Image"
onPress={this.deleteImage}
disabled={disabled}
/>
</div>
</div>
{error &&
<div className="error-message"> {error}</div>
}
</div>
}
</div>
);
}
}
FileInput.propTypes = {
input: object.isRequired,
accept: string,
disabled: bool,
error: string
};
FileInput.defaultProps = {
accept: '*',
};
export default FileInput;
Je sais que l'entrée de fichier est toujours non contrôlée, mais le code suivant fonctionne toujours dans mon propre projet, je peux réinitialiser l'entrée sans aucun problème.
constructor(props) {
super(props);
this.state = {
selectedFile: undefined,
selectedFileName: undefined,
imageSrc: undefined,
value: ''
};
this.handleChange = this.handleChange.bind(this);
this.removeImage = this.removeImage.bind(this);
}
handleChange(event) {
if (event.target.files[0]) {
this.setState({
selectedFile: event.target.files[0],
selectedFileName: event.target.files[0].name,
imageSrc: window.URL.createObjectURL(event.target.files[0]),
value: event.target.value,
});
}
}
// Call this function to reset input
removeImage() {
this.setState({
selectedFile: undefined,
selectedFileName: undefined,
imageSrc: undefined,
value: ''
})
}
render() {
return (
<input type="file" value={this.state.value} onChange={this.handleChange} />
);
}
React n'est rien d'autre que JavaScript et nous pouvons également utiliser la manipulation DOM dans le code React. Cela devrait fonctionner
document.getElementsByClassName('upload')[0].value = null;