web-dev-qa-db-fra.com

Comment réinitialiser l'entrée du fichier ReactJS

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?

8
Stepan Yakovenko

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.

21
Freez

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 = "";
17
Jozcar

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.

12
tonatiuhnb

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. 

1
IRTrapGod

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;
0
Agustina Chaer

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} />
    );
}
0
Jack L.

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;
0
Rastko Sasic