Html 如何重置 ReactJS 文件输入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42192346/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 14:22:42  来源:igfitidea点击:

How to reset ReactJS file input

htmlreactjsfile-upload

提问by Stepan Yakovenko

I have file upload input:

我有文件上传输入:

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

And I handle upload this way:

我以这种方式处理上传:

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

If I upload same file twice, then upload event is not fired. How can I fix that? For simple js code it was enough to do the following: this.value = null; in change handler. How can I do it with ReactJS?

如果我上传相同的文件两次,则不会触发上传事件。我该如何解决?对于简单的 js 代码,执行以下操作就足够了: this.value = null; 在更改处理程序中。我怎样才能用 ReactJS 做到这一点?

回答by Freez

I think you can just clear the input value like this :

我认为您可以像这样清除输入值:

e.target.value = null;

File input cannot be controlled, there is no React specific way to do that.

无法控制文件输入,没有 React 特定的方法来做到这一点。

回答by Jozcar

This work for me - ref={ref => this.fileInput = ref}

这对我有用 - ref={ref => this.fileInput = ref}

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

then in my case once the file was uploaded to the server , I clear it by using the statement below

然后在我的情况下,一旦文件上传到服务器,我就会使用下面的语句清除它

 this.fileInput.value = "";

回答by tonatiuhnb

What worked for me was setting a keyattribute to the file input, then when I needed to reset it I update the key attribute 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>
  )
}

That forces React to render the input again from scratch.

这迫使 React 从头开始​​再次渲染输入。

回答by aelor

I do it by updating keyinside my file input. This will force a re-render and previously selected file will go away.

我通过key在我的文件输入中更新来做到这一点。这将强制重新渲染,并且先前选择的文件将消失。

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

Changing the state inputKeywill re-render the component. One way to change the inputKeywill be to always set it to Date.now()on click of a button which is supposed to clear the field.

更改状态inputKey将重新渲染组件。更改inputKeywill 的一种方法是始终将其设置为Date.now()单击应该清除该字段的按钮。

回答by Elnoor

With every click onClickyou can reset the input, so that even with the same file onChangewill be triggered.

每次点击onClick都可以重置输入,这样即使是同一个文件onChange也会被触发。

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

回答by IRTrapGod

You can also include this in your input element if you know you are not going to be using the built-in file input value at all.

如果您知道您根本不会使用内置文件输入值,您也可以将它包含在您的输入元素中。

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

This way the value is always reset to the empty string on render and you don't have to include it awkwardly in an onChange function.

通过这种方式,值总是在渲染时重置为空字符串,并且您不必笨拙地将它包含在 onChange 函数中。

回答by Hyman L.

I know file input is always uncontrolled however the following code still works in my own porject, I can reset the input with no problems at all.

我知道文件输入总是不受控制,但是以下代码在我自己的项目中仍然有效,我可以毫无问题地重置输入。

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

回答by Agustina Chaer

Here is my solution using redux form

这是我使用 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;

回答by Dani Amsalem

The following worked for me using React Hooks. This is done using what is known as a "controlled input". That means, the inputs are controlledby state, or their source of truth is state.

以下使用 React Hooks 对我有用。这是使用所谓的“受控输入”完成的。这意味着,输入由状态控制,或者它们的真实来源是状态。

TL;DRResetting the file input was a two-step process using both the useState()and useRef()hooks.

TL;DR重置文件输入是一个使用钩子useState()useRef()钩子的两步过程。

NOTE: I also included how I reset a text input in case anyone else was curious.

注意:我还包括了如何重置文本输入以防其他人好奇。

function CreatePost({ user }) {
    const [content, setContent] = React.useState("");
    const [image, setImage] = React.useState(null); //See Supporting Documentation #1
    const imageInputRef = React.useRef(); //See Supporting Documentation #2

    function handleSubmit(event) {
        event.preventDefault(); //Stop the pesky default reload function
        setContent(""); //Resets the value of the first input - See #1

        //////START of File Input Reset
        imageInputRef.current.value = "";//Resets the file name of the file input - See #2
        setImage(null); //Resets the value of the file input - See #1
        //////END of File Input Reset
    }

    return (
    <div>
        <form onSubmit={handleSubmit}>
            <input 
            type="text" 
            placeholder="Add Post Content" 
            onChange={event => setContent(event.target.value)}
            value={content} //Make this input's value, controlled by state
            />
            <input 
            type="file"
            onChange={event => setImage(event.target.files[0])} //See Supporting Doc #3
            ref={imageInputRef} //Apply the ref to the input, now it's controlled - See #2
            />
            <button type="submit">Submit Form</button>
        </form>
    </div>
    )
};

Supporting Documentation:

支持文档:

  1. useState Hook
    • Returns a stateful value, and a function to update it.
  2. useRef Hook
    • If you pass a ref object to React, React will set its current property to the corresponding DOM node whenever that node changes.
  3. Using files from web apps
    • If the user selects just one file, it is then only necessary to consider the first file of the list.
  1. 使用状态钩子
    • 返回一个有状态的值和一个更新它的函数。
  2. 使用引用钩子
    • 如果您将 ref 对象传递给 React,则每当该节点发生更改时,React 都会将其当前属性设置为相应的 DOM 节点。
  3. 使用来自网络应用程序的文件
    • 如果用户只选择一个文件,则只需要考虑列表的第一个文件。