Как сбросить ввод файла ReactJS

У меня есть вход для загрузки файлов:

<input onChange={this.getFile} id="fileUpload" type="file" className="upload"/>

И я обрабатываю загрузку таким образом:

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);
}

Если я загружаю тот же файл дважды, то событие загрузки не запускается. Как я могу это исправить? Для простого js-кода было достаточно сделать следующее: this.value = null; в обработчике изменений. Как я могу это сделать с помощью ReactJS?

Ответы

Ответ 1

Я думаю, вы можете просто очистить входное значение следующим образом:

e.target.value = null;

Вход в файл нельзя контролировать, для этого не существует конкретного способа Реагирования.

Ответ 2

Эта работа для меня - ref = {ref => this.fileInput = ref}

<input id="file_input_file" type="file" onChange={(e) => this._handleFileChange(e)} ref={ref=> this.fileInput = ref} />

то в моем случае, как только файл был загружен на сервер, я очищаю его, используя приведенную ниже инструкцию

 this.fileInput.value = "";

Ответ 3

Для меня работала установка key атрибута ввода файла, а затем, когда мне нужно было его сбросить, я обновляю значение атрибута ключа:

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>
  )
}

Это заставляет React возвращать вход снова с нуля.

Ответ 4

Я делаю это, обновляя key внутри моего файла ввода. Это приведет к повторной визуализации, и ранее выбранный файл исчезнет.

<input type="file" key={this.state.inputKey} />

Изменение состояния inputKey приведет к повторной визуализации компонента. Один из способов изменить inputKey состоит в том, чтобы всегда устанавливать его в Date.now() при нажатии кнопки, которая должна очистить поле.

Ответ 5

Вы также можете включить это в свой элемент ввода, если знаете, что вообще не будете использовать входное значение встроенного файла.

<input value={""} ... />

Таким образом, значение всегда сбрасывается в пустую строку при рендеринге, и вам не нужно неловко включать его в функцию onChange.

Ответ 6

Я знаю, что вход в файл всегда неконтролируемый, однако следующий код по-прежнему работает в моем собственном приложении, я могу сбросить ввод без каких-либо проблем.

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} />
    );
}

Ответ 7

Вот мое решение с использованием редукционной формы

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;

Ответ 8

React - это не что иное, как JavaScript, и мы можем использовать DOM-манипуляции и в коде React. Это должно работать

document.getElementsByClassName('upload') [0].value = null;

Ответ 9

С каждым щелчком onClick вы можете сбросить вход, так что даже с тем же файлом onChange будет срабатывать.

<input onChange={this.onChange} onClick={e => (e.target.value = null)} type="file" />