react-gestion-de-eventos

Gestión de eventos en React

  • 4 min

Ya tenemos componentes. Ahora necesitamos que el usuario pueda interactuar con la interfaz: haciendo clic en botones, escribiendo en formularios o arrastrando elementos.

En React, la gestión de eventos es muy similar al DOM tradicional, pero con algunas diferencias sintácticas y de arquitectura que hacen que nuestro código sea más predecible y compatible entre navegadores.

Sintaxis: React vs HTML

Si venís de escribir HTML clásico, estaréis acostumbrados a esto:

<button onclick="activarLaseras()">Disparar</button>
Copied!

En React (JSX), hay dos diferencias fundamentales:

  1. CamelCase: Los eventos se nombran usando camelCase, no minúsculas. Usamos onClick en vez de onclick, onChange en vez de onchange, etc.
  2. Funciones, no Strings: En JSX pasamos la función tal cual, no un string con código a ejecutar.
// React (JSX)
function Boton() {
  const handleClick = () => {
    alert('Pew pew!');
  };

  return (
    <button onClick={handleClick}>
      Disparar
    </button>
  );
}
Copied!

El error común: Ejecutar vs Referenciar

Fijaos bien en cómo pasamos la función al evento:

  • Correcto (Pasar referencia): onClick={handleClick}
  • Incorrecto (Ejecutar función): onClick={handleClick()}

Si ponéis los paréntesis (), estáis ejecutando la función inmediatamente cuando React renderiza el componente, no cuando el usuario hace clic.

Eventos más comunes

Aunque React soporta prácticamente todos los eventos del navegador, el 90% del tiempo usaréis estos dos:

Se usa para botones, enlaces y elementos interactivos. Funciona igual que el click nativo.

<button onClick={() => setContador(c => c + 1)}>
  Incrementar
</button>
Copied!

Fundamental para formularios. A diferencia del HTML, donde onchange suele dispararse cuando el input pierde el foco (blur), en React onChange se dispara con cada tecla pulsada.

Esto es importante para mantener sincronizado el estado de React con lo que ve el usuario en tiempo real (lo que llamamos Controlled Components, que veremos más adelante).

const [texto, setTexto] = useState('');

return (
  <input 
    type="text" 
    value={texto} 
    onChange={(e) => setTexto(e.target.value)} 
  />
);
Copied!

El objeto SyntheticEvent

En el ejemplo anterior hemos usado un argumento e. ¿Qué es exactamente esa e?

Si inspeccionáis ese objeto en la consola, veréis que no es un evento nativo del DOM. Es un SyntheticEvent.

React implementa su propio sistema de eventos. Es una capa de abstracción (un wrapper) que envuelve al evento nativo del navegador.

Pasando argumentos a los Event Handlers

A menudo, dentro de una lista, querremos pasar un dato específico al handler (por ejemplo, el ID del elemento que queremos borrar).

Como dijimos que no podíamos ejecutar la función directamente. Es decir, no podemos hacer esto

// ❌ Esto no
<button onClick={borrar(id)}>
  Eliminar
</button>
Copied!

Tenemos dos opciones para solucionar esto:

Es la forma más común y moderna. Creamos una función anónima que, al ejecutarse, llama a nuestra función con parámetros.

// ✅ Correcto
<button onClick={() => eliminarUsuario(usuario.id)}>
  Eliminar
</button>
Copied!

Aquí, lo que pasamos a onClick es la definición de la función flecha. React ejecutará esa flecha cuando ocurra el click, y la flecha a su vez ejecutará eliminarUsuario.

Una técnica más funcional, útil si queremos evitar crear arrow functions en cada render (aunque el impacto de rendimiento es despreciable).

const crearHandler  = (id) => () => {
  eliminarUsuario(id);
};

// Uso
<button onClick={crearHandler(usuario.id)}>Eliminar</button>
Copied!

Prevent Default

En HTML, si tenéis un formulario y un botón de submit, al hacer clic la página se recargará. En una SPA (Single Page Application) como las que hacemos con React, queremos evitar esa recarga.

Para ello, usamos e.preventDefault().

function Formulario() {
  const handleSubmit = (e) => {
    // 1. IMPORTANTE: Evitamos la recarga de la página
    e.preventDefault();
    
    // 2. Procesamos los datos
    console.log('Enviando datos...');
  };

  return (
    <form onSubmit={handleSubmit}>
      <button type="submit">Enviar</button>
    </form>
  );
}
Copied!