【问题标题】: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 中工作。

【问题讨论】:

标签: javascript reactjs


【解决方案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 = "" 并且按照stackoverflow.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 = "";
          }
        };
        

        【讨论】:

          猜你喜欢
          • 2011-04-08
          • 2018-03-08
          • 2020-04-15
          • 2020-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-18
          • 2020-06-27
          相关资源
          最近更新 更多