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
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:
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:
// 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:
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:
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.
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. Próximo: Renderizado condicional, donde lo que un componente devuelve comienza a depender de los datos que tiene.

