Ответ 1
Я думаю, вы можете просто очистить входное значение следующим образом:
e.target.value = null;
Вход в файл нельзя контролировать, для этого не существует конкретного способа Реагирования.
У меня есть вход для загрузки файлов:
<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?
Я думаю, вы можете просто очистить входное значение следующим образом:
e.target.value = null;
Вход в файл нельзя контролировать, для этого не существует конкретного способа Реагирования.
Эта работа для меня - 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 = "";
Для меня работала установка 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 возвращать вход снова с нуля.
Я делаю это, обновляя key
внутри моего файла ввода.
Это приведет к повторной визуализации, и ранее выбранный файл исчезнет.
<input type="file" key={this.state.inputKey} />
Изменение состояния inputKey
приведет к повторной визуализации компонента.
Один из способов изменить inputKey
состоит в том, чтобы всегда устанавливать его в Date.now()
при нажатии кнопки, которая должна очистить поле.
Вы также можете включить это в свой элемент ввода, если знаете, что вообще не будете использовать входное значение встроенного файла.
<input value={""} ... />
Таким образом, значение всегда сбрасывается в пустую строку при рендеринге, и вам не нужно неловко включать его в функцию onChange.
Я знаю, что вход в файл всегда неконтролируемый, однако следующий код по-прежнему работает в моем собственном приложении, я могу сбросить ввод без каких-либо проблем.
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} />
);
}
Вот мое решение с использованием редукционной формы
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;
React - это не что иное, как JavaScript, и мы можем использовать DOM-манипуляции и в коде React. Это должно работать
document.getElementsByClassName('upload') [0].value = null;
С каждым щелчком onClick
вы можете сбросить вход, так что даже с тем же файлом onChange
будет срабатывать.
<input onChange={this.onChange} onClick={e => (e.target.value = null)} type="file" />