如何重置ReactJS文件输入

时间:2017-02-12 19:42:29

标签: html5 reactjs file-upload

我有文件上传输入:

<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做到这一点?

11 个答案:

答案 0 :(得分:32)

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

e.target.value = null;

无法控制文件输入,没有特定于React的方法。

答案 1 :(得分:21)

这项工作对我来说 - ref = {ref =&gt; this.fileInput = ref}

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

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

 this.fileInput.value = "";

答案 2 :(得分:13)

对我有用的是为文件输入设置void*属性,然后当我需要重置它时,我更新了键属性值:

key

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

答案 3 :(得分:4)

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

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

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

答案 4 :(得分:4)

以下内容使用React Hooks为我工作。使用所谓的“受控输入”完成此操作。这就是说,输入是受国家控制的,或者它们的真实来源是国家。

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

注意:我还介绍了如何在其他人好奇的情况下重置文本输入。

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

支持文档:

  1. useState Hook
    • 返回有状态值,以及更新它的函数。
  2. useRef Hook
    • 如果将ref对象传递给React,只要该节点发生更改,React就会将其当前属性设置为相应的DOM节点。
  3. Using files from web apps
    • 如果用户仅选择一个文件,则只需考虑列表的第一个文件。

答案 5 :(得分:1)

如果您完全不打算使用内置文件输入值,那么也可以在输入元素中包含此内容。

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

通过这种方法,值始终在渲染时重置为空字符串,而不必在onChange函数中笨拙地包含它。

答案 6 :(得分:1)

每次点击onClick都可以重置输入,以便即使使用相同的文件onChange也将被触发。

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

答案 7 :(得分:0)

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

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

答案 8 :(得分:0)

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

答案 9 :(得分:0)

React只是JavaScript,我们也可以在React代码中使用DOM操作。 这应该可以工作

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

答案 10 :(得分:0)

我们可以使用 <mergingTracksBreakdownStructure> <track id="10"> <mergedTrack id="10"/> <mergedTrack id="11"/> <mergedTrack id="12"/> </track> <track id="13"> <mergedTrack id="13"/> <mergedTrack id="14"/> </track> <track id="15"> <mergedTrack id="15"/> <mergedTrack id="16"/> </track> <track id="27"> <mergedTrack id="27"/> </track> <track id="30"> <mergedTrack id="30"/> </track> </mergingTracksBreakdownStructure> 并在构造函数状态下将<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="/"> <xsl:result-document href="output.xml" method="xml"> <xsl:apply-templates select="document('input.xml')//track"/> </xsl:result-document> </xsl:template> </xsl:stylesheet> 初始化为key = {this.state.fileInputKey}来重置文件输入。 成功上传文件后,我们需要再次分配fileInputKey:Date.now(),使其具有与先前不同的值,并在下一个fileInputKey

上创建新的文件输入组件

我们还可以通过单击按钮清除/重置文件输入来手动执行此操作

下面是工作代码:

Date.now()