Como acionar manualmente o evento de clique no ReactJS?

97

Como posso acionar manualmente um evento de clique no ReactJS ? Quando um usuário clica no element1, desejo acionar automaticamente um clique na inputtag.

<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
fonte
Olhando para algumas bibliotecas externas, parece uma boa ideia fazer o elemento de entrada programaticamente: github.com/okonet/react-dropzone/blob/master/src/index.js#L7
Ahmed Nuaman
Não consigo ver por que você iria querer fazer isso em React. O que você está pensando em fazer?
tobiasandersen,
@tobiasandersen É um caso de uso perfeitamente válido para focar programaticamente um inputelemento, que é provavelmente o que o autor da pergunta deseja realizar com o clique disparado programaticamente.
John Weisz,
Sim, claro, o foco e o desfoque são perfeitamente válidos. Mas clicar? A razão pela qual estou perguntando é que se, por exemplo, foco for o caso de uso, é melhor mostrar isso. Mas se o clique realmente for o caso de uso, então é melhor apenas chamar o manipulador.
tobiasandersen,
@JohnWhite Bem, poderia ser encadernado corretamente :) Mas você provavelmente está certo, e não era minha intenção parecer sarcástico. Só queria ver qual era a real intenção por trás disso.
tobiasandersen

Respostas:

121

Você poderia usar o refprop para adquirir uma referência ao objeto HTMLInputElement subjacente por meio de um retorno de chamada, armazenar a referência como uma propriedade de classe e, em seguida, usar essa referência para acionar posteriormente um clique de seus manipuladores de eventos usando o método HTMLElement.click .

Em seu rendermétodo:

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

Em seu manipulador de eventos:

this.inputElement.click();

Exemplo completo:

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

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

Observe a função de seta ES6 que fornece o escopo léxico correto para thiso retorno de chamada. Observe também que o objeto que você adquire dessa forma é um objeto semelhante ao que você adquiriria usando document.getElementById, ou seja, o nó DOM real.

John Weisz
fonte
7
Isso não está funcionando para mim. Não tenho certeza se está desatualizado, mas atribuí com sucesso o elemento, mas quando o chamo click, ele clickestá indefinido. Posso ver todos os outros atributos e retornos de chamada que atribuí a esse elemento. Alguma ideia?
TheJKFever
40
"Refs não retornam mais um nó DOM de documento, eles retornam uma referência a um nó DOM virtual React" Isso é definitivamente um equívoco. Refs não retornam nós "virtuais DOM". Fonte: Eu trabalho no React.
Dan Abramov de
4
@DanAbramov Então qual é o método recomendado para isso?
painel de
1
@JohnWeisz Muito obrigado, funcionou para mim, tive essa necessidade de lidar com o clique fora do Form porque eu tinha que colocar alguns elementos entre o botão e o formulário.
Markus Ethur,
1
Funciona para mim. Coloquei o elemento de entrada em -100 com posição absoluta, depois no meu código ref={(ref)=>{this.fileUploadRef = ref}e no meu botãoonClick={()=>{this.fileUploadRef.click()}}
Richard
20

Usei o seguinte para funcionar em maio de 2018 com o ES6 React Docs como referência: 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 Codes Alot
fonte
Parece uma resposta mais orientada para a reação .
Ritik
8

Você pode usar o refretorno de chamada que retornará o node. Chame click()esse nó para fazer um clique programático.

Obtendo o div

clickDiv(el) {
  el.click()
}

Configurando um refpara o div

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

Verifique o violino

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

Espero que ajude!

Pranesh Ravi
fonte
quando você vincula a um jsfiddle, é considerado uma boa prática colocar pelo menos o código relevante aqui (aliás: o editor de snippet também oferece suporte a reactjs)
Icepickle,
4
É importante notar que, embora a abordagem ref string não seja descontinuada, ela é considerada uma funcionalidade legada que foi substituída pela sintaxe baseada em callback: ref={elem => this.elem = elem}- Isso é detalhado em Refs to Components .
John Weisz
1
@JohnWhite Sugestão válida. Atualizou a resposta!
Pranesh Ravi,
Além disso, você precisa verificar e certificar- else de que não é nulo / indefinido antes de fazer isso.
janeiro
4

Em um componente funcional, esse princípio também funciona, é apenas uma sintaxe e uma maneira de pensar ligeiramente 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>
    </>
  )

}
Tijolo Imutável
fonte
2

Experimente e me avise se não funcionar no seu lado:

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

Clicar em divdeve simular um clique no inputelemento

Alex Oleksiiuk
fonte
2

Aqui estão a solução 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
fonte
"myRefname.current.focus não é uma função"
Spoderman4
1

Usando React Hooks e o useRefhook .

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
fonte
Para mim, isso não estava funcionando, pois o clique e o foco não estavam disponíveis. Mas o que funcionou é esta resposta, stackoverflow.com/a/54316368/3893510 se em vez de tentar fazer myInput.current? .Click (); Você faz: myInput.current.dispatchEvent (new MouseEvent ('click', {view: window, bubbles: true, cancelable: true, buttons: 1,}),); Deve funcionar
jackbridger
1

Refletindo sobre a resposta de Aaron Hakala com useRef inspirado nesta resposta 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,
      }),
    );
  };

E seu JSX:

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

Se não funcionar na versão mais recente do reactjs, tente 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
fonte
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>

Este trabalho para mim

Arslan
fonte
-2

Que tal simplesmente o velho js? exemplo:

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
fonte
Expectaion in React
Nitin Kumar,