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 hace clic, guardar un formulario, abrir un menú, eliminar un elemento. React lo maneja igual que todo lo demás: a través de props. En lugar de llamar a addEventListener como hiciste en el capítulo de eventos de 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 la conectas es un patrón de React propio.

Vincular un manejador

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

Los props de evento se nombran en camelCase, coincidiendo con el evento que escuchan: onClick para clics, onChange cuando cambia el valor de un campo, onSubmit cuando se envía un formulario. Escribes el prop en el elemento y le das una función para ejecutar.

handleClick se define dentro del componente, luego se pasa a onClick. React la llama cada vez que se hace clic en el botón. Estás pasando la función por nombre, handleClick. Llamarla, handleClick(), la ejecutaría inmediatamente durante el render. Le estás entregando a React la función para que la ejecute después, no la ejecutas tú ahora mismo.

Cuando necesitas detalles sobre 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. Dale un nombre a 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 donde se disparó el evento, y event.target.value es el texto actual en el campo. Solo necesitas recurrir al objeto event cuando un manejador realmente necesita esa información. El onClick de un botón a menudo no lo necesita.

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 misma, React la llama después, al hacer clic
<button onClick={handleClick}>Guardar</button>

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

Pasar manejadores 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 a un hijo como un prop, igual 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 la pasa a SaveButton bajo el nombre de prop onSave. SaveButton no sabe ni le importa qué hace la función, solo la vincula a onClick. Así es cómo un clic en un componente pequeño y reutilizable termina disparando lógica que vive más arriba en tu app, más cerca del state o de los datos que esa lógica necesita.

Prevenir el comportamiento predeterminado

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> mismo, 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 del mismo, normalizando las diferencias entre navegadores para que el mismo código funcione en todos lados sin que tengas que verificar cuál 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 escuchador a cada elemento que tiene un prop onClick u onChange. Adjunta un solo escuchador 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 de la misma forma para elementos que no existen aún cuando la app se renderiza por primera vez, un elemento añadido a una lista después aún dispara su onClick correctamente, porque el escuchador en la raíz nunca fue vinculado a ese elemento específico en primer lugar.

JunoLos manejadores son funciones en props Los props de evento se nombran como onClick y onChange, y les das una función para ejecutar, no el resultado de ejecutar una. Escribe onClick={handleClick}, nunca onClick={handleClick()}. Cuando un manejador necesita detalles sobre qué sucedió, atrápala con un parámetro llamado event.
JunoLos manejadores son funciones en props Adjunta manejadores con props en camelCase como onClick, onChange y onSubmit, y pasa la referencia de la función, no una llamada a ella. Define un manejador en un padre y pásalo 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á sacudiendo 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 solo escuchador en la raíz en lugar de uno por elemento, confiando en bubbling para enrutar el evento al manejador correcto. La regla cotidiana sigue siendo válida debajo de todo: dale a React la función, no la llames tú mismo, y recurre a event.preventDefault() en el onSubmit de un formulario para tomar el control sobre la navegación predeterminada del navegador.

Próximo: Renderizado condicional, donde lo que un componente devuelve comienza a depender de los datos que tiene.