Manejo de eventos en React

El manejo de eventos de los elementos en React es similar al de los elementos del DOM. Sin embargo, hay una diferencia sintáctica:

  • Los nombres de los atributos para el enlace de eventos en React usan la escritura camelCase, en lugar de minúsculas.
  • Si usas la sintaxis de JSX, debes pasar una función como manejador de eventos, en lugar de una cadena (como en el DOM).

La escritura habitual en HTML es:

<button onclick="activateLasers()">
  激活按钮
</button>

En React se escribe:

<button onClick={activateLasers}>
  激活按钮
</button>

En React, otra diferencia es que no puedes usar returnfalsede esta manera para evitar el comportamiento predeterminado, debes usar explícitamentepreventDefault。

Por ejemplo, normalmente en HTML, para evitar que un enlace abra una nueva página por defecto, podemos escribir:
<a href="../index.html" onclick="console.log('点击链接'); return false">
  点我
</a>

En React, la forma de escribirlo es:

function ActionLink() { function handleClick(e) { e.preventDefault(); console.log('Enlace clickeado'); } return ( <a href="#" onClick={handleClick}> Haz clic </a> ); }

En el ejemplo, e es un evento sintético.

Cuando usas React, normalmente no necesitas usar addEventListener para agregar un listener a un elemento DOM ya creado. Solo necesitas proporcionar un listener cuando el elemento se renderiza inicialmente.

Cuando usas la sintaxis de clase de ES6 para definir un componente, el manejador de eventos se convierte en un método de la clase. Por ejemplo, el siguiente componente Toggle renderiza un botón que permite al usuario alternar el estado de un interruptor:

Ejemplo

class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; //Aquí es necesario el enlace (binding) para que `this` pueda usarse en la función de callback. this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'} </button> ); } } const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <Toggle />, document.getElementById('example') );

Pruébalo »

Debes tener cuidado con this en las funciones de callback de JSX. Los métodos de una clase no están vinculados a this por defecto. Si olvidas vincular this.handleClick y lo pasas a onClick, el valor de this será undefined cuando llames a esta función.

Normalmente, si no agregas () después del método, por ejemploonClick={this.handleClick}, debes vincular this para este método.

Si usar bind te resulta molesto, aquí hay dos formas de resolverlo. Si estás usando la sintaxis experimental de inicializadores de propiedades, puedes usar inicializadores de propiedades para vincular correctamente la función de callback:

class LoggingButton extends React.Component { //Esta sintaxis asegura que `this` esté vinculado en handleClick. //Esto es solo una prueba. handleClick = () => { console.log('this is:', this); } render() { return ( <button onClick={this.handleClick}> Click me </button> ); } }

Si no usas la sintaxis de inicializadores de propiedades, puedes usar funciones de flecha en la función de callback:

class LoggingButton extends React.Component { handleClick() { console.log('this is:', this); } render() { //Esta sintaxis asegura que `this` esté vinculado en handleClick. return ( <button onClick={(e) => this.handleClick(e)}> Click me </button> ); } }

Usar esta sintaxis tiene el problema de que cada vez que LoggingButton se renderiza, se crea una función de callback diferente. En la mayoría de los casos, esto no es un problema. Sin embargo, si esta función de callback se pasa como valor de una propiedad a componentes de nivel inferior, esos componentes pueden realizar renderizados adicionales. Normalmente recomendamos vincular en el constructor o usar la sintaxis de inicializadores de propiedades para evitar este tipo de problemas de rendimiento.


Pasar parámetros al manejador de eventos

Normalmente pasamos parámetros adicionales al manejador de eventos. Por ejemplo, si id es el id de la fila que quieres eliminar, las siguientes dos formas pueden pasar parámetros al manejador de eventos:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
Las dos formas anteriores son equivalentes.

En los dos ejemplos anteriores, el parámetro e, como objeto de evento de React, se pasará como segundo parámetro. Con las funciones de flecha, el objeto de evento debe pasarse explícitamente; pero con bind, el objeto de evento y más parámetros se pasarán implícitamente.

Es importante notar que al pasar parámetros a la función de escucha mediante bind, en una función de escucha definida en un componente de clase, el objeto de evento e debe colocarse después de los parámetros pasados, por ejemplo:

class Popper extends React.Component{ constructor(){ super(); this.state = {name:'Hello world!'}; } preventPop(name, e){ //El objeto de evento e debe colocarse al final. e.preventDefault(); alert(name); } render(){ return ( <div> <p>hello</p> {/*Pasar parámetros mediante el método bind().*/} <a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a> </div> ); } }
Otras extensiones