如何允许输入类型=文件在反应组件中选择相同的文件

Posted

技术标签:

【中文标题】如何允许输入类型=文件在反应组件中选择相同的文件【英文标题】:How to allow input type=file to select the same file in react component 【发布时间】:2017-01-21 22:22:52 【问题描述】:

我有一个反应组件,它呈现一个<input type="file"> dom 以允许用户从浏览器中选择图像。我发现当我选择同一个文件时,它的 onChange 方法没有被调用。经过一番搜索,有人建议在 onChange 方法的末尾使用this.value=nullreturn false,但我试过它不起作用。

下面是我的代码:

<input id="upload" ref="upload" type="file" accept="image/*"
           onChange=(event)=>  this.readFile(event) />

以下是我尝试过的:

<input id="upload" ref="upload" type="file" accept="image/*"
               onChange=(event)=>  
                   this.readFile(event) 
                   return false
              />

另一个是:

<input id="upload" ref="upload" type="file" accept="image/*"
           onChange=(event)=>  
               this.readFile(event) 
               this.value=null
          />

我相信上述解决方案适用于 jquery,但我不知道如何让它在 reactjs 中工作。

【问题讨论】:

这只是与反应无关的浏览器行为,文件没有改变。见***.com/questions/4109276/… 这能回答你的问题吗? html input file selection event not firing upon selecting the same file 【参考方案1】:

this thread的副本

<input id="upload" ref="upload" type="file" accept="image/*"
           onChange=(event)=>  
               this.readFile(event) 
          
        onClick=(event)=>  
               event.target.value = null
          

/>

【讨论】:

这对我有用!我不建议使用内联函数,但这个概念很有效。 使用 TypeScript,event.target.value = null 我得到了编译错误TS2322: Type 'null' is not assignable to type 'string'. 但我可以说event.target.value = "" 并且按照***.com/a/56258902/2848676 工作【参考方案2】:

我认为您的函数中的this 没有引用input 字段。尝试改用event.target

<input id="upload" ref="upload" type="file" accept="image/*"
           onChange=(event)=>  
               this.readFile(event) 
               event.target.value=null
          />

【讨论】:

我刚试过,但它不起作用。第二次选择同一个文件时不会触发onChange方法。 使用onInput 而不是onChange 设置 event.target.value=null 对我有用,谢谢!【参考方案3】:

对我来说确实有效:event.currentTarget.value = null

    onClick=(event)=>  
               event.currentTarget.value = null
          

【讨论】:

打字稿版本类似于(event.target as HTMLInputElement).value = null;【参考方案4】:

我的 React 版本:16.2.0

@jbsmoove 解决方案适用于除 IE11 以外的所有浏览器。

对于 IE11,如果我们打开某个文件并且第二次按取消而不是打开文件,它会显示空白屏幕,在控制台中我们会看到:

无法获取未定义或空引用的属性“名称”

所以我想出了另一种即使在 IE11 中也能完美运行的解决方案:

<input id="upload" ref="upload" type="file" accept="image/*"
      onInput=(event)=>  
           this.readFile(event) 
      
      onClick=(event)=>  
           event.target.value = null
      
/>

只需使用 onInput 而不是 onChange

【讨论】:

【参考方案5】:

以下是我的解决方案。 (使用打字稿)

import * as React from "react";

export class FileSelector extends React.Component<undefined, undefined>

    constructor(props: any)
    
        super(props);
        this.handleChange = this.handleChange.bind(this);
    

    handleChange(selectorFiles: FileList)
    
        console.log(selectorFiles);
    

    render ()
    
        return <div>
            <input type="file" onChange= (e) => this.handleChange(e.target.files)  />
        </div>;
    

【讨论】:

这个回答是不是忽略了它应该调用event.target.value = "" 的要点。或者更具体地说&lt;input alt="Upload Demand" type="file" onChange= (ie) =&gt; this.handleUploadDemand(ie); ie.target.value = ""/&gt;【参考方案6】:

使用后备点击方法来选择相同的图像。 示例:

  <input
    id="upload" 
    ref="upload" 
    type="file" 
    accept="image/*"       
    multiple="false"
    onChange=(e) => this.getDailyImage(e)
    onClick=(e) => e.target.files[0] && this.getDailyImage(e)
  />

【讨论】:

【参考方案7】:

我通常只在输入上使用key prop 来重置它在选择之间的底层 DOM 节点(在更改处理程序中使用一些增量 UID 计数器或上传/处理状态标志):

const UploadInput = (props) => 
  const [isUploading, setUploading] = useState(false);

  const handleChange = useCallback((async (e) => 
    setUploading(true); // or setUID((old) => old + 1);

    try 
      await ... // handle processing here
     finally 
      setUploading(false);
    
  , [...]);

  return (
    <div className=...>
      <input key=isUploading type="file" onChange=handleChange ...props />

      isUploading && <Spinner />
    </div>
  );
;

另一种方法可能是获取表单的ref 并在处理后使用formRef.reset()(如果您在文件处理后不关心表单内容,则可行)。

【讨论】:

【参考方案8】:

我通过使用 Typescript 在我的 input 中添加以下 onchange 事件侦听器来让我的工作。

const onInputFileChange = (
  event: ChangeEvent<HTMLInputElement>
): void => 
  const nativeEvent = event.nativeEvent.target as HTMLInputElement;
  const targetEvent = event.target as HTMLInputElement;
  if (targetEvent.files && targetEvent.files[0]) 
    const imageFile = targetEvent.files[0];
    // eslint-disable-next-line no-param-reassign
    nativeEvent.value = "";
  
;

【讨论】:

以上是关于如何允许输入类型=文件在反应组件中选择相同的文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在故事书中配置 webpack 以允许 babel 在项目文件夹之外导入反应组件

如何在Vue 2中处理文件上传

如何在反应钩子中创建一个新的 JSON 对象?

如何检测同一文件的输入类型=文件“更改”?

包裹反应16和每个组件SCSS

在反应中,当路由路径不同但组件相同时。如何防止重新安装?