¿Cómo activar manualmente el evento de clic en ReactJS?

97

¿Cómo puedo activar manualmente un evento de clic en ReactJS ? Cuando un usuario hace clic en element1, quiero activar automáticamente un clic en la inputetiqueta.

<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>
Mamata Hegde
fuente
Al observar
Ahmed Nuaman
No veo por qué querrías hacer esto en React. ¿Qué estás buscando hacer?
tobiasandersen
@tobiasandersen Es un caso de uso perfectamente válido enfocar programáticamente un inputelemento, que es probablemente lo que el autor de la pregunta quiere lograr con el clic activado mediante programación.
John Weisz
Sí, claro, tanto el enfoque como el desenfoque son perfectamente válidos. ¿Pero haciendo clic? La razón por la que pregunto es que si, por ejemplo, el enfoque es el caso de uso, entonces es mejor mostrarlo. Pero si hacer clic es realmente el caso de uso, entonces es mejor simplemente llamar al controlador.
tobiasandersen
@JohnWhite Bueno, podría estar encuadernado correctamente :) Pero probablemente tengas razón, y no era mi intención parecer sarcástico. Solo quería ver cuál era la verdadera intención detrás de esto.
tobiasandersen

Respuestas:

121

Puede usar el refaccesorio para adquirir una referencia al objeto HTMLInputElement subyacente a través de una devolución de llamada, almacenar la referencia como una propiedad de clase y luego usar esa referencia para activar más tarde un clic de sus controladores de eventos usando el método HTMLElement.click .

En tu rendermétodo:

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

En su controlador de eventos:

this.inputElement.click();

Ejemplo completo:

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

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

Tenga en cuenta la función de flecha ES6 que proporciona el alcance léxico correcto thisen la devolución de llamada. También tenga en cuenta que el objeto que adquiere de esta manera es un objeto similar al que adquiriría utilizando document.getElementById, es decir, el nodo DOM real.

John Weisz
fuente
7
Esto no me funciona. No estoy seguro de si está desactualizado, pero asigno correctamente el elemento, pero cuando lo llamo click, clickno está definido. Puedo ver todos los demás atributos y devoluciones de llamada que le he asignado a ese elemento. ¿Algunas ideas?
TheJKFever
40
"Las referencias ya no devuelven un nodo DOM de documento, devuelven una referencia a un nodo DOM virtual de React" Definitivamente es un error. Las referencias no devuelven nodos "DOM virtual". Fuente: trabajo en React.
Dan Abramov
4
@DanAbramov Entonces, ¿cuál es el método recomendado para esto?
panel
1
@JohnWeisz Muchas gracias, funcionó para mí, tuve esta necesidad de manejar con un clic fuera del formulario porque tuve que poner algunos elementos entre el botón y el formulario.
Markus Ethur
1
Funciona para mi. Puse el elemento de entrada en -100 con posición absoluta, luego en mi código ref={(ref)=>{this.fileUploadRef = ref}y luego en mi botónonClick={()=>{this.fileUploadRef.click()}}
Richard
20

Obtuve lo siguiente para trabajar en mayo de 2018 con ES6 React Docs como referencia: 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;
Sir códigos mucho
fuente
Esto parece una respuesta más orientada a Reaccionar .
Ritik
8

Puede usar la refdevolución de llamada que devolverá el node. Llame click()a ese nodo para hacer un clic programático.

Obteniendo el divnodo

clickDiv(el) {
  el.click()
}

Establecer un refal divnodo

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

Revisa el violín

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

¡Espero eso ayude!

Pranesh Ravi
fuente
cuando se vincula a un jsfiddle, se considera una buena práctica poner al menos el código relevante aquí (por cierto: el editor de fragmentos también admite reactjs)
Icepickle
4
Vale la pena señalar que, si bien el enfoque de referencia de cadena no está en desuso, se considera una funcionalidad heredada que se reemplaza por la sintaxis basada en devolución de llamada: ref={elem => this.elem = elem}- Esto se detalla en Refs to Components .
John Weisz
1
@JohnWhite Sugerencia válida. ¡Actualización de la respuesta!
Pranesh Ravi
Además, debe verificar y asegurarse de que elno sea nulo / indefinido antes de hacer eso.
janex
4

En un componente funcional, este principio también funciona, es solo una sintaxis y una forma de pensar ligeramente diferentes.

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

}
Ladrillo inmutable
fuente
2

Pruebe esto y avíseme si no funciona en su extremo:

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

Al hacer clic en divdebe simular un clic en el inputelemento

Alex Oleksiiuk
fuente
2

Aquí está la solución Hooks

    import React, {useRef} from 'react';

    const MyComponent = () =>{

    const myRefname= useRef(null);

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

    return (
      <div onClick={handleClick}>
        <input ref={myRefname}/>
      </div>
     );
    }
Sajad Saderi
fuente
"myRefname.current.focus no es una función"
Spoderman4
1

Usando React Hooks y el useRefgancho .

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
fuente
Para mí, esto no funcionaba ya que el clic y el enfoque no estaban disponibles. Pero, ¿qué funcionó es esta respuesta, stackoverflow.com/a/54316368/3893510 si en lugar de intentar hacer myInput.current? .Click (); Usted lo hace: myInput.current.dispatchEvent (new MouseEvent ('clic', {vista: ventana, burbujas: verdadero, cancelable: verdadero, botones: 1,}),); Debería funcionar
jackbridger
1

Reflexionando sobre la respuesta de Aaron Hakala con useRef inspirado en esta respuesta 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,
      }),
    );
  };

Y tu JSX:

<button onClick={() => clickElement(myRef)}>Click<button/>
<input ref={myRef}>
jackbridger
fuente
0

Si no funciona en la última versión de reactjs, intente usar 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
fuente
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>

Esto funciona para mi

arslan
fuente
-2

¿Qué tal simplemente viejos js? ejemplo:

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
fuente
La expectativa está en React
Nitin Kumar