How to allow input type=file to select the same file in react component

JavascriptReactjs

Javascript Problem Overview


I have a react component which renders a <input type="file"> dom to allow user select images from browser. I found that its onChange method not called when I select the same file. After some searching, someone suggests using this.value=null or return false at the end of the onChange method but I have tried it doesn't work.

Below is my code:

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

Below is what I tried:

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

Another one is:

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

I believe above solutions work for jquery but I don't know how to let it work in reactjs.

Javascript Solutions


Solution 1 - Javascript

Dup of this thread

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

/>

Solution 2 - Javascript

I think this in your function does not refer to input field. Try using event.target instead.

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

Solution 3 - Javascript

For me actually worked: event.currentTarget.value = null

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

Solution 4 - Javascript

My React version: 16.2.0

@jbsmoove solution works fine for all browsers except IE11.

As for IE11, in case if we Open some file and in second time we press Cancel insteed of Open file it shows empty screen and in console we see:

> Unable to get property 'name' of undefined or null reference

So I've come up with another solution which works perfect even in IE11:

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

Just use onInput instead of onChange.

Solution 5 - Javascript

Below is my solution. (Using Typescript)

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

Solution 6 - Javascript

Use a fallback on-Click method to select the same image. Example:

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

Solution 7 - Javascript

I usually just use key prop on input to reset it's underlying DOM node between selections (either use some incremental UID counter in change handler or uploading/processing state flag):

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

Another way might be to get ref of the form and use formRef.reset() after processing (viable if you don't care for form contents after file processing).

Solution 8 - Javascript

I got mine to work by adding the following onchange event listener in my input, using Typescript.

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 = "";
  }
};

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJoey Yi ZhaoView Question on Stackoverflow
Solution 1 - JavascriptJames BowlerView Answer on Stackoverflow
Solution 2 - JavascriptSkriptotajsView Answer on Stackoverflow
Solution 3 - JavascriptErnane LuisView Answer on Stackoverflow
Solution 4 - JavascriptMike MikeView Answer on Stackoverflow
Solution 5 - JavascriptYash VekariaView Answer on Stackoverflow
Solution 6 - JavascriptSM ChinnaView Answer on Stackoverflow
Solution 7 - JavascriptankhzetView Answer on Stackoverflow
Solution 8 - JavascriptAkinjiola ToniView Answer on Stackoverflow