Skip to content
This page has been auto-translated and may contain errors.View in English

Eventos

Ya construiste un botón. Ahora necesita hacer algo cuando alguien lo haga clic, guardar un formulario, abrir un menú, eliminar un elemento. React maneja esto de la misma forma que maneja todo lo demás: a través de props. En lugar de llamar a addEventListener como hiciste en el capítulo de eventos en JavaScript, pasas una función directamente a un prop en el elemento que quieres escuchar. La idea es la misma: una función que se ejecuta cuando algo sucede, pero la forma en que lo conectas es un patrón de React único.

Adjuntar un manejador

jsx
function SaveButton() {
  function handleClick() {
    console.log('clicked')
  }
  return <button onClick={handleClick}>Guardar</button>
}

Los props de eventos tienen nombres en camelCase, coincidiendo con el evento que escuchan: onClick para clics, onChange para cambios de valor en un campo, onSubmit para el envío de un formulario. Escribes el prop en el elemento y le das una función para ejecutar.

handleClick se define dentro del componente, y luego se pasa a onClick. React la ejecuta cada vez que se hace clic en el botón. Estás pasando la función por nombre, handleClick. Ejecutarla, handleClick(), la correría inmediatamente, durante el renderizado. Lo que haces es entregarle a React la función para ejecutar después, no ejecutarla tú ahora mismo.

Cuando necesitas detalles de qué sucedió, React pasa a tu manejador un objeto event con las mismas propiedades familiares, target, preventDefault(), y demás, que esperarías de addEventListener. Nombra un parámetro para capturarlo, convencionalmente event:

jsx
function SearchBox() {
  function handleChange(event) {
    console.log(event.target.value)
  }
  return <input onChange={handleChange} />
}

event.target es el elemento en el que se disparó el evento, y event.target.value es el texto actual en el campo. Solo necesitas acceder al objeto event cuando un manejador realmente necesita esa información. El onClick de un botón frecuentemente no.

El error más común

Porque el manejador es una función que pasas a un prop, este es un error que atrapa a casi todos en algún momento:

jsx
// Incorrecto: ejecuta handleClick inmediatamente, mientras el componente se renderiza
<button onClick={handleClick()}>Guardar</button>

// Correcto: pasa la función en sí, React la ejecuta después, al hacer clic
<button onClick={handleClick}>Guardar</button>

Los paréntesis son toda la diferencia. handleClick() ejecuta la función en ese instante, durante el renderizado, y lo que retorna (usualmente undefined) es lo que termina en onClick. handleClick le entrega a React la función en sí, para que la llame cuando el clic realmente suceda. Si un manejador parece ejecutarse por su cuenta en el momento en que la página carga, casi siempre es por esto.

Pasar manejadores hacia abajo como props

Un manejador no tiene que vivir en el mismo componente que el elemento al que está adjunto. Puedes definirlo en un padre y pasarlo hacia abajo a un hijo como un prop, de la misma forma que pasarías cualquier otro valor:

jsx
function SaveButton({ onSave }) {
  return <button onClick={onSave}>Guardar</button>
}

function Form() {
  function handleSave() {
    console.log('guardado')
  }
  return <SaveButton onSave={handleSave} />
}

Form es dueño de handleSave y lo pasa a SaveButton bajo el nombre de prop onSave. SaveButton no sabe ni le importa qué hace la función, solo la conecta a onClick. Así es como un clic en un componente pequeño y reutilizable termina activando lógica que vive más arriba en tu app, más cerca del state o los datos que esa lógica necesita.

Prevenir el comportamiento por defecto

Algunos eventos vienen con comportamiento del navegador adjunto, y enviar un formulario es el que encontrarás primero. Por defecto, enviar un formulario recarga la página, lo que descarta cualquier cosa que tu componente estuviera haciendo. Llama a event.preventDefault() dentro del manejador para evitar eso:

jsx
function SignupForm() {
  function handleSubmit(event) {
    event.preventDefault()
    console.log('formulario enviado')
  }
  return (
    <form onSubmit={handleSubmit}>
      <input type="email" />
      <button type="submit">Registrarse</button>
    </form>
  )
}

Adjunta onSubmit al <form> en sí, no onClick al botón. De esa forma, presionar Enter dentro del campo también envía el formulario, no solo hacer clic en el botón.

El objeto event que React te pasa no es el evento nativo del navegador. Es un wrapper que React construye alrededor de él, normalizando las diferencias entre navegadores para que el mismo código funcione en todos lados sin que tengas que verificar qué navegador disparó el evento. Lleva las propiedades que esperarías, target, preventDefault(), key, y demás, pero es el objeto propio de React.

React tampoco adjunta un listener a cada elemento que tiene un prop onClick u onChange. Adjunta un único listener en la raíz de tu app y usa event bubbling para averiguar cuál manejador del componente debe ejecutarse para un evento dado. Por eso el manejo de eventos funciona igual para elementos que no existen aún cuando la app se renderiza por primera vez: un elemento agregado a una lista después aún dispara su onClick correctamente, porque el listener en la raíz nunca estuvo vinculado a ese elemento específico en primer lugar.

JunoLos manejadores son funciones en props Los props de eventos se nombran como onClick y onChange, y les das una función para ejecutar, no el resultado de ejecutarla. Escribe onClick={handleClick}, nunca onClick={handleClick()}.

Cuando un manejador necesita detalles de qué sucedió, captúralos con un parámetro nombrado event.

JunoLos manejadores son funciones en props Adjunta manejadores con props en camelCase como onClick, onChange, y onSubmit, y pasa la referencia a la función, no una llamada a ella.

Define un manejador en un padre y pásalo hacia abajo a un hijo como un prop cuando la lógica pertenece más arriba. Y llama a event.preventDefault() en un manejador de envío, o la página se recargará bajo tu state.

JunoLos manejadores son funciones en props El objeto event de React es un wrapper sintético sobre el nativo, normalizado entre navegadores, y React adjunta un único listener en la raíz en lugar de uno por elemento, confiando en el bubbling para enrutar el evento al manejador correcto.

La regla cotidiana sigue siendo válida bajo la superficie: entrégale a React la función, no la llames tú mismo, y recurre a event.preventDefault() en el onSubmit de un formulario para tomar control de la navegación por defecto del navegador.

Siguiente: Renderizado condicional, donde lo que un componente retorna comienza a depender de los datos que tiene.