34

I have a INPUT BUTTON and INPUT FILE, I want to click the BUTTON and it will trigger the INPUT FILE event in REACT JS.

React.createElement('input',{type:'file', name:'myfile'})

then the button

React.createElement('a',{onClick: this.doClick},'Select File')

So how to define and trigger the INPUT FILE click event when we click the A HREF?

Your help is appreciate. :-)

0

9 Answers 9

66

Update: Sep 18, 2021

Note: On NextJS, I was facing onChange event is not trigged from input file element. For that, we can use onInputCapture or onChangeCapture. For more detailed information, Stackoverflow - onChange event is not firing

Basic example on onChangeCapture as per our requirement. Requires React ^16.8,

const Dummy = () => {
  const inputFileRef = React.useRef();
  const onFileChangeCapture = ( e: React.ChangeEvent<HTMLInputElement> ) {
    /*Selected files data can be collected here.*/
    console.log(e.target.files);
  };
  const onBtnClick = () => {
    /*Collecting node-element and performing click*/
    inputFileRef.current.click();
  };
  return (
    <form>
      <input
        type="file"
        ref={inputFileRef}
        onChangeCapture={onFileChangeCapture}
      />
      <button onClick={onBtnClick}>Select file</button>
    </form>
  );
};

Using useRef Hook in functional components. Requires React ^16.8,

const Dummy = () => {
  const inputFileRef = useRef( null );

  const onFilechange = ( e ) => {
    /*Selected files data can be collected here.*/
    console.log( e.target.files );
  }
  const onBtnClick = () => {
    /*Collecting node-element and performing click*/
    inputFileRef.current.click();
  }

  return (
    <form className="some-container">
      <input
        type="file"
        ref={inputFileRef}
        onChange={onFileChange}
      />
      <button onClick={onBtnClick}>Select file</button>
    </form>
  )
}

Class Implementation with React.createRef() and handling click with node element.

class Dummy extends React.Component {
    
  constructor( props ) {
    super( props );

    this.inputFileRef = React.createRef();
    this.onFileChange = this.handleFileChange.bind( this );
    this.onBtnClick = this.handleBtnClick.bind( this );
  }

  handleFileChange( e ) {
    /*Selected files data can be collected here.*/
    console.log( e.target.files );
  }

  handleBtnClick() {
    /*Collecting node-element and performing click*/
    this.inputFileRef.current.click();
  }

  render() {
    return (
      <form className="some-container">
        <input
          type="file"
          ref={this.inputFileRef}
          onChange={this.onFileChange}
        />
        <button onClick={this.onBtnClick}>Select file</button>
      </form>
    )
  }
}
Sign up to request clarification or add additional context in comments.

6 Comments

This is the right approach and rightfully should have been an accepted answer.
so how to save the uploaded file in state variable? I added a onChange in input but it is not working ??
handle it using onChange property in input tag. <input type="file" onChange={( e ) => e.target.files[0]} /> More info
How do you ensure that the ref has been populated though? It doesn't trigger a render, so the first render the ref is always null in a funcctional component. Is it considered a best practice to just re-render every first time just to grab ref instances?
this.onBtnClick = this.handleBtnClick.bind( this ); ====> should be ====> this.onBtnClick = this.onBtnClick.bind( this );
|
40

You don't need jQuery for this. You don't even need an event handler. HTML has a specific element for this, called label.

First, make sure your input element has an id attribute:

React.createElement('input',{type:'file', name:'myfile', id:'myfile'})

Then, instead of:

React.createElement('a',{onClick: this.doClick},'Select File')

Try:

React.createElement('label',{htmlFor: 'myfile'},'Select File')

(Instead of adding htmlFor and id attributes, another solution is to make the input element a child of the label.)

Now clicking the label should trigger the same behaviour as clicking the input itself.

Comments

35

You could trigger the input type file with ref, f.e:

on your class component:

<input 
    ref={fileInput => this.fileInput = fileInput} 
    type="file"
 />
<button onClick={this.triggerInputFile}> Select File </button>

and make a function on that class component too:

triggerInputFile = () => this.fileInput.click()

Comments

7

Using Hooks with useref:

import React, {useRef} from 'react';
const FancyInput = () => {
    const fileInput = useRef(null)

    const handleClick = () => {
        fileInput.current.click()
    }

    const handleFileChange = event => {
        console.log("Make something")
    }

    return(
        <div className="patientactions-container">
            <input
                type="file"
                onChange={(e) => handleFileChange(e)}
                ref={fileInput} 
            />
            <div onClick={() => handleClick()}></div>
        </div>
    )
}
export default FancyInput;

1 Comment

I tried this but I keep getting the error Object is possibly 'null'. when attempting to run fileInput.current.click(). I tried using an if statement to only run it if fileInput.current !== null but I am still getting the error. Any ideas?
4

Building on the answer from @YÒGÎ , here is an implementation using TypeScript:

class Dummy extends React.Component {
    fileInputRef: React.RefObject<HTMLInputElement> = React.createRef();

    forwardClickToInputElement = () => {
        this.fileInputRef.current!.click();
    };

    handleUploadDemand = (ie: ChangeEvent<HTMLInputElement>) => {
        const fileList: FileList = ie.target.files;

        // do something with the FileList, for example:
        const fileReader = new FileReader();
        fileReader.onload = () => {
            const str = String(fileReader.result);
            try {
                const parsedContent = YOUR_OWN_PARSING(str);
            } catch (error) {
                // YOUR OWN ERROR HANDLING
            }
        };
        fileReader.readAsBinaryString(fileList[0])
    }

    render() {
        return (
            <div className="some-container">
                <button onClick={this.forwardClickToInputElement}>Select File</button>
                <input ref={this.fileInputRef} type="file" onChange={this.handleSelectFile} hidden={true}/>
            </div>
        )
    }
}

References:

  1. Solution for how to use refs in React with Typescript https://stackoverflow.com/a/50505931/2848676
  2. Use ! operator for ref type narrowing https://medium.com/@martin_hotell/react-refs-with-typescript-a32d56c4d315

Comments

3

For those who want to implement Farid's answer in Typescript, can do the following:

import React, {useRef} from 'react';
const FancyInput = () => {
  const fileInput = useRef<HTMLInputElement>(null)

  const handleClick = () => {
    if(fileInput.current) {
      fileInput.current.click()
    }
  }

  const handleFileChange = event => {
      console.log("Make something")
  }

  return(
      <div className="patientactions-container">
          <input
              type="file"
              onChange={(e) => handleFileChange(e)}
              ref={fileInput} 
          />
          <div onClick={() => handleClick()}></div>
      </div>
  )
}
export default FancyInput;

Comments

2

Anyone Looking for a Simple approach try this.

<div>
  <input type="file" name="library-images" id="library-images" hidden />
     <Button type='button' onClick={()=>{
                document.getElementById("library-images")?.click()
     }}>Upload</Button>
</div>

Comments

0
const CustomInput = () => {
  const handleClick = () => {
    document.getElementById("file_upload").click();
  };

  const handleFileChange = (event) => {
    console.log("Make something");
  };

  return (
    <div className="patientactions-container">
      <input type="file" id="file_upload" onChange={(e) => handleFileChange(e)} />
      <div onClick={() => handleClick()}></div>
    </div>
  );
};
export default CustomInput;

Comments

-24

EDIT: This is a question I answered a long time ago not knowing very much react at this time. The fun thing is that it has been considered valid ^^.

So for anyone reading this answer; this answer is wrong and is a very good example of something you shouldn't do in react.

Please find below a nice anti-pattern, again, don't do it.

=================================================

You can achieve this using jQuery:

this.doClick: function() {
    $('input[type=file]').trigger('click');
}

React does not provide specific functions to trigger events, you can use jQuery or simply native Javascript: see Creating and triggering events on MDN

4 Comments

React.createElement('input',{type:'file', name:'myfile'}) then the button React.creatElement('a',{onClick: this.doClick},'Select File') So how to define and trigger the INPUT FILE click event when we click the A HREF?
Yes, currently I always do like that, but what I need is to find is there any way to trigger by REACT, not by JQUERY
The reason one would use React is to get away from jQuery. This answer is poor.
jQuery completely gives control of the DOM and react does the opposite. It's highly recommended that they should never be used together.

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.