91

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.

2

13 Answers 13

161

Dup of this thread

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

/>
Sign up to request clarification or add additional context in comments.

5 Comments

This worked for me! I do recommend not using inline functions but the concept works.
With TypeScript, event.target.value = null I got the compilation error TS2322: Type 'null' is not assignable to type 'string'. But I was able to say event.target.value = "" and that worked as per stackoverflow.com/a/56258902/2848676
With typescript and with what Michael Osofsky wrote, then this worked for me, onClick={(e : MouseEvent) => { const element = e.target as HTMLInputElement; element.value = ''; }}
In typescript use below code onClick={(event) => { event.currentTarget.value = ""; }}
in this case, it didn't work " onClick={(event)=> { setShowAlert(false); event.target.value = null }} "
24

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

4 Comments

I just tried but it doesn't work. the onChange method is not triggered when selecting the same file on the second time.
use onInput instead of onChange
Setting event.target.value=null worked for me, thanks!
this works as well as onChange is triggered the first time
19

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

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

2 Comments

The typescript version goes like (event.target as HTMLInputElement).value = null;
As mentioned below (e.target as HTMLInputElement).value = "";
15

After hours of online research this worked for ME on Reactjs

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

/>

1 Comment

This is also the only solution that worked for me. I am using ReactJs.
10

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.

Comments

6

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

1 Comment

Isn't this answering missing the point in that it should call event.target.value = "". Or more specifically <input alt="Upload Demand" type="file" onChange={ (ie) => {this.handleUploadDemand(ie); ie.target.value = ""}}/>}
2

If we want to update same file(same name) multiple times we will get above error. To avoide we need to assign null value for the currentTarget after first time updated the file.

Ex.

const handleFile = useCallback(e => {

    const MAX_FILE_SIZE = (fileSize.MAX_FILE_SIZE_MANAGE_TAGS * 1024)

    if (e.target.files.length > 0) {

        const uploadedFileSize = e.target.files[0].size / 1024

        if (uploadedFileSize < MAX_FILE_SIZE) {

            uploadFile(e.target.files[0]) // you will get current uploaded value

            e.currentTarget.value = null // this the place where we need to assign null value

        } else {
            console.log('file is large')
        }
    }
}, [ ])



<Button
    className={classes.uploadButton}
    component="label"
>
    Upload File
    <input
        onChange={handleFile}
        type="file"
        accept=".xlsx"
        hidden
    />
</Button>

Comments

1

Typescript way without assertion.

  <input
      id="upload"
      ref="upload"
      type="file"
      accept="image/*"
      onChange={(e: ChangeEvent<HTMLInputElement>) => {
                this.readFile(e)
      }}
      onClick={(e: MouseEvent<HTMLInputElement>) => {
                e.currentTarget.value = "";
      }}
   />

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
1

This forces it to 'change' the file each time even if the same file is selected again.

<input type="file" value="" />

Comments

0

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

Comments

0

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).

Comments

0

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

Comments

0

If you are using multiple file to upload try currentTarget.value

  <input id='uploadFile' type="file" onClick={(e)=> {e.currentTarget.value = null}}  onChange={onChangeGetFilesSelected}  multiple={true} accept=".xlsx,.xls,.doc, .docx,.ppt, .pptx,.txt,.pdf"/>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.