160

How can I manually trigger a click event in ReactJS? When a user clicks on element1, I want to automatically trigger a click on the input tag.

<div className="div-margins logoContainer">
  <div id="element1" className="content" onClick={this.uploadLogoIcon}>
    <div className="logoBlank" />
  </div>
  <input accept="image/*" type="file" className="hide"/>
</div>
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
Mamata Hegde
  • 1,629
  • 2
  • 9
  • 10
  • Looking at some external libraries, it seems a good idea to make the input element programmatically: https://github.com/okonet/react-dropzone/blob/master/src/index.js#L7 – Ahmed Nuaman Oct 07 '16 at 09:26
  • I can't see why you would ever want to do this in React. What are you looking to do? – tobiasandersen Oct 07 '16 at 09:37
  • @tobiasandersen It is a perfectly valid use-case to programmatically focus an `input` element, which is likely what the asker wants to accomplish with the programmatically triggered click. – John Weisz Oct 07 '16 at 09:49
  • Yeah sure, both focus and blur are perfectly valid. But clicking? The reason I'm asking is that if e.g. focusing is the use case, then it's better to show that. But if click really is the use case, then it's better to just call the handler. – tobiasandersen Oct 07 '16 at 09:57
  • @JohnWhite Well it could be bound correctly :) But you're probably right, and it wasn't my meaning to come off snarky. Just wanted to see what the real intention behind this was. – tobiasandersen Oct 07 '16 at 10:08

14 Answers14

164

You could use the ref prop to acquire a reference to the underlying HTMLInputElement object through a callback, store the reference as a class property, then use that reference to later trigger a click from your event handlers using the HTMLElement.click method.

In your render method:

<input ref={input => this.inputElement = input} ... />

In your event handler:

this.inputElement.click();

Full example:

class MyComponent extends React.Component {
  render() {
    return (
      <div onClick={this.handleClick}>
        <input ref={input => this.inputElement = input} />
      </div>
    );
  }

  handleClick = (e) => {
    this.inputElement.click();
  }
}

Note the ES6 arrow function that provides the correct lexical scope for this in the callback. Also note, that the object you acquire this way is an object akin to what you would acquire using document.getElementById, i.e. the actual DOM-node.

John Weisz
  • 30,137
  • 13
  • 89
  • 132
  • 7
    This is not working for me. Not sure if it's out of date, but I successfully assign the element, but when I call `click` on it, `click` is undefined. I can see all the other attributes and callbacks that I've assigned to that element. Any ideas? – TheJKFever May 21 '17 at 20:51
  • @TheJKFever -- It's impossible to tell without knowing your code, but it is likely that the reference you are obtaining is in-fact _not_ an `HTMLInputElement` object. What does `instanceof this.inputElement` give? – John Weisz May 30 '17 at 11:35
  • this doesn't work for me either, click is undefined. – venkatareddy Jul 13 '17 at 07:00
  • @TheJKFever Refs no longer return a document DOM node, they return reference to a React virtual DOM node. To get a reference to the document node, import `ReactDOM` and use `const domNode = ReactDOM.findDOMNode(ref)`. – Simon Robb Oct 18 '17 at 01:35
  • 62
    "Refs no longer return a document DOM node, they return reference to a React virtual DOM node" That's definitely a misconception. Refs don't return "virtual DOM" nodes. Source: I work on React. – Dan Abramov Nov 20 '17 at 20:07
  • 5
    @DanAbramov So what's the recommended method for this ? – alegria Aug 14 '18 at 12:24
  • 1
    @JohnWeisz Thank you soooooo much, it worked for me, I had this necessity to handle with click outside of Form because I hade to put some elements between the button and form. – Markus Ethur Oct 22 '18 at 13:25
  • 1
    Works for me. I put the input element at -100 with absolute position, then in my code `ref={(ref)=>{this.fileUploadRef = ref}` and then my button `onClick={()=>{this.fileUploadRef.click()}}` – Richard Oct 23 '18 at 04:27
  • 3
    @TheJKFever If you're in TypeScript, click might be undefined because input is of type; `HTMLInputElement | null;`, therefore use: `onClick={() => { if(inputElement) (inputElement).click(); } }` to get it to compile! – Jamie Twells Feb 21 '19 at 22:10
  • Heads-up that if you do an `e.preventDefault()` in your event handler this won't work. – mgalgs May 15 '19 at 03:58
  • In functional components it worked perfectly for me using the useRef hook. I used it in the KeyDown event – Diego Lope Loyola May 18 '22 at 20:25
  • While it may work, using this solution with ``e.preventDefault()`` doesn't seem to be good practice. As a workaround, you can include it in an if statement: ``if (e) e.preventDefault()``. – Houssem Apr 26 '23 at 09:52
42

Here is the Hooks solution:

import React, {useRef} from 'react';

const MyComponent = () => {
    const myRefname= useRef<HTMLInputElement>(null);
    const handleClick = () => {
        myRefname.current.focus();
     }

    return (
        <div onClick={handleClick}>
            <input ref={myRefname}/>
        </div>
    );
}
S.Saderi
  • 4,755
  • 3
  • 21
  • 23
32

Got the following to work May 2018 with ES6 React Docs as a reference: https://reactjs.org/docs/refs-and-the-dom.html

import React, { Component } from "react";
class AddImage extends Component {
  constructor(props) {
    super(props);
    this.fileUpload = React.createRef();
    this.showFileUpload = this.showFileUpload.bind(this);
  }
  showFileUpload() {
    this.fileUpload.current.click();
  }
  render() {
    return (
      <div className="AddImage">
        <input
          type="file"
          id="my_file"
          style={{ display: "none" }}
          ref={this.fileUpload}
        />
        <input
          type="image"
          src="http://www.graphicssimplified.com/wp-content/uploads/2015/04/upload-cloud.png"
          width="30px"
          onClick={this.showFileUpload}
        />
      </div>
    );
  }
}
export default AddImage;
n4m31ess_c0d3r
  • 3,028
  • 5
  • 26
  • 35
Sir Codes Alot
  • 1,149
  • 8
  • 11
10

You can use ref callback which will return the node. Call click() on that node to do a programmatic click.

Getting the div node

clickDiv(el) {
  el.click()
}

Setting a ref to the div node

<div 
  id="element1"
  className="content"
  ref={this.clickDiv}
  onClick={this.uploadLogoIcon}
>

Check the fiddle

https://jsfiddle.net/pranesh_ravi/5skk51ap/1/

Hope it helps!

tobiasandersen
  • 8,480
  • 3
  • 28
  • 39
Pranesh Ravi
  • 18,642
  • 9
  • 46
  • 70
  • when you link to a jsfiddle, it's concidered a good practise to put at least the relevant code in here (btw: the snippet editor supports reactjs as well) – Icepickle Oct 07 '16 at 09:33
  • 4
    It is worth noting that while the string ref approach is not deprecated, it is considered legacy functionality that is superseded by the callback-based syntax: `ref={elem => this.elem = elem}` -- This is detailed in [Refs to Components](https://facebook.github.io/react/docs/more-about-refs.html). – John Weisz Oct 07 '16 at 09:42
  • 1
    @JohnWhite Valid suggestion. Updated the answer! – Pranesh Ravi Oct 07 '16 at 09:47
  • 1
    Also, you need to check and make sure `el` isn't null/undefined before you do that. – janex May 18 '18 at 19:23
9

In a functional component this principle also works, it's just a slightly different syntax and way of thinking.

const UploadsWindow = () => {
  // will hold a reference for our real input file
  let inputFile = '';

  // function to trigger our input file click
  const uploadClick = e => {
    e.preventDefault();
    inputFile.click();
    return false;
  };

  return (
    <>
      <input
        type="file"
        name="fileUpload"
        ref={input => {
          // assigns a reference so we can trigger it later
          inputFile = input;
        }}
        multiple
      />

      <a href="#" className="btn" onClick={uploadClick}>
        Add or Drag Attachments Here
      </a>
    </>
  )

}
Immutable Brick
  • 830
  • 12
  • 23
6

Riffing on Aaron Hakala's answer with useRef inspired by this answer https://stackoverflow.com/a/54316368/3893510

const myRef = useRef(null);

  const clickElement = (ref) => {
    ref.current.dispatchEvent(
      new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true,
        buttons: 1,
      }),
    );
  };

And your JSX:

<button onClick={() => clickElement(myRef)}>Click<button/>
<input ref={myRef}>
Jack Bridger
  • 165
  • 2
  • 14
5

Using React Hooks and the useRef hook.

import React, { useRef } from 'react';

const MyComponent = () => {
    const myInput = useRef(null);

    const clickElement = () => {
        // To simulate a user focusing an input you should use the
        // built in .focus() method.
        myInput.current?.focus();

        // To simulate a click on a button you can use the .click()
        // method.
        // myInput.current?.click();
    }

    return (
        <div>
            <button onClick={clickElement}>
                Trigger click inside input
            </button>
            <input ref={myInput} />
        </div>
    );
}
Aaron Hakala
  • 302
  • 4
  • 7
  • For me this wasn't working as click and focus were not available. But what did work is this answer, https://stackoverflow.com/a/54316368/3893510 if instead of trying to do myInput.current?.click(); You do: myInput.current.dispatchEvent( new MouseEvent('click', { view: window, bubbles: true, cancelable: true, buttons: 1, }), ); It should work – Jack Bridger Sep 28 '20 at 14:04
  • What is the meaning of ? in myInput.current?.focus(); – Julio de Leon Jan 27 '21 at 02:57
  • @JuliodeLeon it is "optional chaining" - introduced recently in JavaScript https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining It's used when you want to access or a call a function on an object that may be undefined. – Jack Bridger Feb 02 '21 at 20:33
5
this.buttonRef.current.click();
Skoua
  • 3,373
  • 3
  • 38
  • 51
2

Try this and let me know if it does not work on your end:

<input type="checkbox" name='agree' ref={input => this.inputElement = input}/>
<div onClick={() => this.inputElement.click()}>Click</div>

Clicking on the div should simulate a click on the input element

Alex Oleksiiuk
  • 338
  • 2
  • 9
1
  let timer;
  let isDoubleClick = false;

  const handleClick = () => {
    if(!isDoubleClick) {
      isDoubleClick = true;
      timer = setTimeout(() => {
        isDoubleClick = false;
        props.onClick();
      }, 200);
    } else {
      clearTimeout(timer);
      props.onDoubleClick();
    }
  }

return <div onClick={handleClick}></div>
Matt E
  • 25
  • 5
1

for typescript you could use this code to avoid getting type error

import React, { useRef } from 'react';

const MyComponent = () => {
    const fileRef = useRef<HTMLInputElement>(null);

    const handleClick = () => {
      fileRef.current?.focus();
    }

    return (
        <div>
            <button onClick={handleClick}>
                Trigger click inside input
            </button>
            <input ref={fileRef} />
        </div>
    );
}
  • 1
    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](/help/how-to-answer). – Community Apr 13 '22 at 08:14
0

If it doesn't work in the latest version of reactjs, try using innerRef

class MyComponent extends React.Component {


  render() {
    return (
      <div onClick={this.handleClick}>
        <input innerRef={input => this.inputElement = input} />
      </div>
    );
  }

  handleClick = (e) => {
    this.inputElement.click();
  }
}
mXaln
  • 105
  • 11
0

  imagePicker(){
        this.refs.fileUploader.click();
        this.setState({
            imagePicker: true
        })
    }
  <div onClick={this.imagePicker.bind(this)} >
  <input type='file'  style={{display: 'none'}}  ref="fileUploader" onChange={this.imageOnChange} /> 
  </div>

This work for me

arslan
  • 1,064
  • 10
  • 19
-3

How about just plain old js ? example:

autoClick = () => {
 if (something === something) {
    var link = document.getElementById('dashboard-link');
    link.click();
  }
};
  ......      
var clickIt = this.autoClick();            
return (
  <div>
     <Link id="dashboard-link" to={'/dashboard'}>Dashboard</Link>
  </div>
);
taggartJ
  • 277
  • 2
  • 6